* coff-h8300.c: Fix formatting.
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index df035315d3e6466d15218f272e8bc15f2569dfe1..bc81458987a637031222f9d6da15d2009f3b0ece 100644 (file)
@@ -345,7 +345,7 @@ static bfd_reloc_status_type mips_elf_calculate_relocation
   PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
           const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
           Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
-          boolean *));
+          boolean *, boolean));
 static bfd_vma mips_elf_obtain_contents
   PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
 static boolean mips_elf_perform_relocation
@@ -364,6 +364,7 @@ static INLINE int elf_mips_isa PARAMS ((flagword));
 static INLINE char* elf_mips_abi_name PARAMS ((bfd *));
 static void mips_elf_irix6_finish_dynamic_symbol
   PARAMS ((bfd *, const char *, Elf_Internal_Sym *));
+static boolean _bfd_mips_elf_mach_extends_p PARAMS ((flagword, flagword));
 
 /* This will be used when we sort the dynamic relocation records.  */
 static bfd *reldyn_sorting_bfd;
@@ -1486,7 +1487,7 @@ mips_elf_got_page (abfd, info, value, offsetp)
 
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
-  /* Look to see if we aleady have an appropriate entry.  */
+  /* Look to see if we already have an appropriate entry.  */
   last_entry = sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
   for (entry = (sgot->contents
                + MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO);
@@ -1639,7 +1640,7 @@ mips_elf_sort_hash_table (info, max_local)
                               &hsd);
 
   /* There should have been enough room in the symbol table to
-     accomodate both the GOT and non-GOT symbols.  */
+     accommodate both the GOT and non-GOT symbols.  */
   BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
 
   /* Now we know which dynamic symbol has the lowest dynamic symbol
@@ -1900,6 +1901,7 @@ mips_elf_create_got_section (abfd, info)
   flagword flags;
   register asection *s;
   struct elf_link_hash_entry *h;
+  struct bfd_link_hash_entry *bh;
   struct mips_got_info *g;
   bfd_size_type amt;
 
@@ -1919,13 +1921,14 @@ mips_elf_create_got_section (abfd, info)
   /* Define the symbol _GLOBAL_OFFSET_TABLE_.  We don't do this in the
      linker script because we don't want to define the symbol if we
      are not creating a global offset table.  */
-  h = NULL;
+  bh = NULL;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
          (bfd_vma) 0, (const char *) NULL, false,
-         get_elf_backend_data (abfd)->collect,
-         (struct bfd_link_hash_entry **) &h)))
+         get_elf_backend_data (abfd)->collect, &bh)))
     return false;
+
+  h = (struct elf_link_hash_entry *) bh;
   h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
   h->type = STT_OBJECT;
@@ -2003,7 +2006,7 @@ static bfd_reloc_status_type
 mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
                               relocation, addend, howto, local_syms,
                               local_sections, valuep, namep,
-                              require_jalxp)
+                              require_jalxp, save_addend)
      bfd *abfd;
      bfd *input_bfd;
      asection *input_section;
@@ -2016,6 +2019,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
      bfd_vma *valuep;
      const char **namep;
      boolean *require_jalxp;
+     boolean save_addend;
 {
   /* The eventual value we will return.  */
   bfd_vma value;
@@ -2040,7 +2044,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
   struct mips_elf_link_hash_entry *h = NULL;
   /* True if the symbol referred to by this relocation is a local
      symbol.  */
-  boolean local_p;
+  boolean local_p, was_local_p;
   /* True if the symbol referred to by this relocation is "_gp_disp".  */
   boolean gp_disp_p = false;
   Elf_Internal_Shdr *symtab_hdr;
@@ -2068,6 +2072,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   local_p = mips_elf_local_relocation_p (input_bfd, relocation,
                                         local_sections, false);
+  was_local_p = local_p;
   if (! elf_bad_symtab (input_bfd))
     extsymoff = symtab_hdr->sh_info;
   else
@@ -2455,10 +2460,19 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
         order.  We don't need to do anything special here; the
         differences are handled in mips_elf_perform_relocation.  */
     case R_MIPS_GPREL16:
-      if (local_p)
-       value = mips_elf_sign_extend (addend, 16) + symbol + gp0 - gp;
-      else
-       value = mips_elf_sign_extend (addend, 16) + symbol - gp;
+      /* Only sign-extend the addend if it was extracted from the
+        instruction.  If the addend was separate, leave it alone,
+        otherwise we may lose significant bits.  */
+      if (howto->partial_inplace)
+       addend = mips_elf_sign_extend (addend, 16);
+      value = symbol + addend - gp;
+      /* If the symbol was local, any earlier relocatable links will
+        have adjusted its addend with the gp offset, so compensate
+        for that now.  Don't do it for symbols forced local in this
+        link, though, since they won't have had the gp offset applied
+        to them before.  */
+      if (was_local_p)
+       value += gp0;
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
@@ -2491,7 +2505,9 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       break;
 
     case R_MIPS_GPREL32:
-      value = (addend + symbol + gp0 - gp) & howto->dst_mask;
+      value = (addend + symbol + gp0 - gp);
+      if (!save_addend)
+       value &= howto->dst_mask;
       break;
 
     case R_MIPS_PC16:
@@ -2937,6 +2953,12 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
         know where the shared library will wind up at load-time.  */
       outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
                                     R_MIPS_REL32);
+      outrel[1].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
+                                    ABI_64_P (output_bfd)
+                                    ? R_MIPS_64
+                                    : R_MIPS_NONE);
+      outrel[2].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
+                                    R_MIPS_NONE);
 
       /* Adjust the output offset of the relocation to reference the
         correct location in the output file.  */
@@ -3058,9 +3080,18 @@ _bfd_elf_mips_mach (flags)
     case E_MIPS_MACH_4111:
       return bfd_mach_mips4111;
 
+    case E_MIPS_MACH_4120:
+      return bfd_mach_mips4120;
+
     case E_MIPS_MACH_4650:
       return bfd_mach_mips4650;
 
+    case E_MIPS_MACH_5400:
+      return bfd_mach_mips5400;
+
+    case E_MIPS_MACH_5500:
+      return bfd_mach_mips5500;
+
     case E_MIPS_MACH_SB1:
       return bfd_mach_mips_sb1;
 
@@ -3644,7 +3675,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
      sh_offset == object size, and ld doesn't allow that.  While the check
      is arguably bogus for empty or SHT_NOBITS sections, it can easily be
      avoided by not emitting those useless sections in the first place.  */
-  if ((IRIX_COMPAT (abfd) != ict_irix5 && (IRIX_COMPAT (abfd) != ict_irix6))
+  if (! SGI_COMPAT (abfd) && ! NEWABI_P(abfd)
       && (sec->flags & SEC_RELOC) != 0)
     {
       struct bfd_elf_section_data *esd;
@@ -3815,15 +3846,17 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       && strcmp (*namep, "__rld_obj_head") == 0)
     {
       struct elf_link_hash_entry *h;
+      struct bfd_link_hash_entry *bh;
 
       /* Mark __rld_obj_head as dynamic.  */
-      h = NULL;
+      bh = NULL;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, *namep, BSF_GLOBAL, *secp,
              (bfd_vma) *valp, (const char *) NULL, false,
-             get_elf_backend_data (abfd)->collect,
-             (struct bfd_link_hash_entry **) &h)))
+             get_elf_backend_data (abfd)->collect, &bh)))
        return false;
+
+      h = (struct elf_link_hash_entry *) bh;
       h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
       h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
       h->type = STT_OBJECT;
@@ -3879,6 +3912,7 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
      struct bfd_link_info *info;
 {
   struct elf_link_hash_entry *h;
+  struct bfd_link_hash_entry *bh;
   flagword flags;
   register asection *s;
   const char * const *namep;
@@ -3937,13 +3971,14 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
     {
       for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
        {
-         h = NULL;
+         bh = NULL;
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr,
                  (bfd_vma) 0, (const char *) NULL, false,
-                 get_elf_backend_data (abfd)->collect,
-                 (struct bfd_link_hash_entry **) &h)))
+                 get_elf_backend_data (abfd)->collect, &bh)))
            return false;
+
+         h = (struct elf_link_hash_entry *) bh;
          h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
          h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
          h->type = STT_SECTION;
@@ -3959,7 +3994,7 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
            return false;
        }
 
-      /* Change aligments of some sections.  */
+      /* Change alignments of some sections.  */
       s = bfd_get_section_by_name (abfd, ".hash");
       if (s != NULL)
        bfd_set_section_alignment (abfd, s, 4);
@@ -3979,26 +4014,17 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
 
   if (!info->shared)
     {
-      h = NULL;
-      if (SGI_COMPAT (abfd))
-       {
-         if (!(_bfd_generic_link_add_one_symbol
-               (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr,
-                (bfd_vma) 0, (const char *) NULL, false,
-                get_elf_backend_data (abfd)->collect,
-                (struct bfd_link_hash_entry **) &h)))
-           return false;
-       }
-      else
-       {
-         /* For normal mips it is _DYNAMIC_LINKING.  */
-         if (!(_bfd_generic_link_add_one_symbol
-               (info, abfd, "_DYNAMIC_LINKING", BSF_GLOBAL,
-                bfd_abs_section_ptr, (bfd_vma) 0, (const char *) NULL, false,
-                get_elf_backend_data (abfd)->collect,
-                (struct bfd_link_hash_entry **) &h)))
-           return false;
-       }
+      const char *name;
+
+      name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
+      bh = NULL;
+      if (!(_bfd_generic_link_add_one_symbol
+           (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
+            (bfd_vma) 0, (const char *) NULL, false,
+            get_elf_backend_data (abfd)->collect, &bh)))
+       return false;
+
+      h = (struct elf_link_hash_entry *) bh;
       h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
       h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
       h->type = STT_SECTION;
@@ -4015,26 +4041,15 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
          s = bfd_get_section_by_name (abfd, ".rld_map");
          BFD_ASSERT (s != NULL);
 
-         h = NULL;
-         if (SGI_COMPAT (abfd))
-           {
-             if (!(_bfd_generic_link_add_one_symbol
-                   (info, abfd, "__rld_map", BSF_GLOBAL, s,
-                    (bfd_vma) 0, (const char *) NULL, false,
-                    get_elf_backend_data (abfd)->collect,
-                    (struct bfd_link_hash_entry **) &h)))
-               return false;
-           }
-         else
-           {
-             /* For normal mips the symbol is __RLD_MAP.  */
-             if (!(_bfd_generic_link_add_one_symbol
-                   (info, abfd, "__RLD_MAP", BSF_GLOBAL, s,
-                    (bfd_vma) 0, (const char *) NULL, false,
-                    get_elf_backend_data (abfd)->collect,
-                    (struct bfd_link_hash_entry **) &h)))
-               return false;
-           }
+         name = SGI_COMPAT (abfd) ? "__rld_map" : "__RLD_MAP";
+         bh = NULL;
+         if (!(_bfd_generic_link_add_one_symbol
+               (info, abfd, name, BSF_GLOBAL, s,
+                (bfd_vma) 0, (const char *) NULL, false,
+                get_elf_backend_data (abfd)->collect, &bh)))
+           return false;
+
+         h = (struct elf_link_hash_entry *) bh;
          h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
          h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
          h->type = STT_OBJECT;
@@ -5251,7 +5266,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                             input_section, info, rel,
                                             addend, howto, local_syms,
                                             local_sections, &value,
-                                            &name, &require_jalx))
+                                            &name, &require_jalx,
+                                            use_saved_addend_p))
        {
        case bfd_reloc_continue:
          /* There's nothing to do.  */
@@ -5935,10 +5951,22 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
       val = E_MIPS_ARCH_3 | E_MIPS_MACH_4111;
       break;
 
+    case bfd_mach_mips4120:
+      val = E_MIPS_ARCH_3 | E_MIPS_MACH_4120;
+      break;
+
     case bfd_mach_mips4650:
       val = E_MIPS_ARCH_3 | E_MIPS_MACH_4650;
       break;
 
+    case bfd_mach_mips5400:
+      val = E_MIPS_ARCH_4 | E_MIPS_MACH_5400;
+      break;
+
+    case bfd_mach_mips5500:
+      val = E_MIPS_ARCH_4 | E_MIPS_MACH_5500;
+      break;
+
     case bfd_mach_mips5000:
     case bfd_mach_mips8000:
     case bfd_mach_mips10000:
@@ -6107,9 +6135,14 @@ _bfd_mips_elf_modify_segment_map (abfd)
 
   /* For IRIX 6, we don't have .mdebug sections, nor does anything but
      .dynamic end up in PT_DYNAMIC.  However, we do have to insert a
-     PT_OPTIONS segement immediately following the program header
+     PT_OPTIONS segment immediately following the program header
      table.  */
-  if (ABI_64_P (abfd))
+  if (NEWABI_P (abfd)
+      /* On non-IRIX6 new abi, we'll have already created a segment
+        for this section, so don't create another.  I'm not sure this
+        is not also the case for IRIX 6, but I can't test it right
+        now.  */
+      && IRIX_COMPAT (abfd) == ict_irix6)
     {
       for (s = abfd->sections; s; s = s->next)
        if (elf_section_data (s)->this_hdr.sh_type == SHT_MIPS_OPTIONS)
@@ -6122,7 +6155,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
          /* Usually, there's a program header table.  But, sometimes
             there's not (like when running the `ld' testsuite).  So,
             if there's no program header table, we just put the
-            options segement at the end.  */
+            options segment at the end.  */
          for (pm = &elf_tdata (abfd)->segment_map;
               *pm != NULL;
               pm = &(*pm)->next)
@@ -6369,12 +6402,13 @@ _bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
    _bfd_elf_link_hash_copy_indirect copy the flags for us.  */
 
 void
-_bfd_mips_elf_copy_indirect_symbol (dir, ind)
+_bfd_mips_elf_copy_indirect_symbol (bed, dir, ind)
+     struct elf_backend_data *bed;
      struct elf_link_hash_entry *dir, *ind;
 {
   struct mips_elf_link_hash_entry *dirmips, *indmips;
 
-  _bfd_elf_link_hash_copy_indirect (dir, ind);
+  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 
   if (ind->root.type != bfd_link_hash_indirect)
     return;
@@ -6791,7 +6825,7 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
          asymbol *sym = *(*parent)->sym_ptr_ptr;
          if (bfd_is_abs_section (sym->section) && abfd)
            {
-             /* The special_function wouldn't get called anyways.  */
+             /* The special_function wouldn't get called anyway.  */
            }
          else if (!gp_found)
            {
@@ -6983,6 +7017,8 @@ _bfd_mips_elf_final_link (abfd, info)
                    <= g->global_gotno);
     }
 
+#if 0
+  /* We want to set the GP value for ld -r.  */
   /* On IRIX5, we omit the .options section.  On IRIX6, however, we
      include it, even though we don't process it quite right.  (Some
      entries are supposed to be merged.)  Empirically, we seem to be
@@ -7020,6 +7056,7 @@ _bfd_mips_elf_final_link (abfd, info)
          break;
        }
     }
+#endif
 
   /* Get a value for the GP register.  */
   if (elf_gp (abfd) == 0)
@@ -7633,6 +7670,26 @@ _bfd_mips_elf_final_link (abfd, info)
   return true;
 }
 \f
+/* Return true if machine EXTENSION is an extension of machine BASE,
+   meaning that it should be safe to link code for the two machines
+   and set the output machine to EXTENSION.  EXTENSION and BASE are
+   both submasks of EF_MIPS_MACH.  */
+
+static boolean
+_bfd_mips_elf_mach_extends_p (base, extension)
+     flagword base, extension;
+{
+  /* The vr5500 ISA is an extension of the core vr5400 ISA, but doesn't
+     include the multimedia stuff.  It seems better to allow vr5400
+     and vr5500 code to be merged anyway, since many libraries will
+     just use the core ISA.  Perhaps we could add some sort of ASE
+     flag if this ever proves a problem.  */
+  return (base == 0
+         || (base == E_MIPS_MACH_5400 && extension == E_MIPS_MACH_5500)
+         || (base == E_MIPS_MACH_4100 && extension == E_MIPS_MACH_4111)
+         || (base == E_MIPS_MACH_4100 && extension == E_MIPS_MACH_4120));
+}
+
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -7739,10 +7796,9 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
 
       /* If either has no machine specified, just compare the general isa's.
         Some combinations of machines are ok, if the isa's match.  */
-      if (! new_mach
-         || ! old_mach
-         || new_mach == old_mach
-         )
+      if (new_mach == old_mach
+         || _bfd_mips_elf_mach_extends_p (new_mach, old_mach)
+         || _bfd_mips_elf_mach_extends_p (old_mach, new_mach))
        {
          /* Don't warn about mixing code using 32-bit ISAs, or mixing code
             using 64-bit ISAs.  They will normally use the same data sizes
@@ -7759,8 +7815,11 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
          else
            {
              /* Do we need to update the mach field?  */
-             if (old_mach == 0 && new_mach != 0) 
-               elf_elfheader (obfd)->e_flags |= new_mach;
+             if (_bfd_mips_elf_mach_extends_p (old_mach, new_mach))
+               {
+                 elf_elfheader (obfd)->e_flags &= ~EF_MIPS_MACH;
+                 elf_elfheader (obfd)->e_flags |= new_mach;
+               }
 
              /* Do we need to update the ISA field?  */
              if (new_isa > old_isa)
This page took 0.029599 seconds and 4 git commands to generate.