1999-09-04 Steve Chamberlain <sac@pobox.com>
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index cdcf65cbfe0a65085111626ce84fa5a9362fedb7..3d4ddf5ffac49a8da7f329fa11eaf941c500ba4a 100644 (file)
@@ -98,6 +98,8 @@ static bfd_reloc_status_type mips32_64bit_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
+static reloc_howto_type *mips_rtype_to_howto
+  PARAMS ((unsigned int));
 static void mips_info_to_howto_rel
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
 static void mips_info_to_howto_rela
@@ -163,8 +165,8 @@ static boolean mips_elf_record_global_got_symbol
           struct mips_got_info *));
 static bfd_vma mips_elf_got_page
   PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
-static boolean mips_elf_next_lo16_addend
-  PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *, bfd_vma *));
+static const Elf_Internal_Rela *mips_elf_next_lo16_relocation
+  PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *));
 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 *,
@@ -190,9 +192,10 @@ static bfd_vma mips_elf_create_local_got_entry
   PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));
 static bfd_vma mips_elf_got16_entry 
   PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
-static unsigned int mips_elf_create_dynamic_relocation 
+static boolean mips_elf_create_dynamic_relocation 
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
-          long, bfd_vma, asection *));
+          struct mips_elf_link_hash_entry *, asection *,
+          bfd_vma, bfd_vma *, asection *));
 static void mips_elf_allocate_dynamic_relocations 
   PARAMS ((bfd *, unsigned int));
 static boolean mips_elf_stub_section_p 
@@ -600,7 +603,7 @@ static reloc_howto_type elf_mips_howto_table[] =
         _bfd_mips_elf_got16_reloc,     /* special_function */
         "R_MIPS_GOT16",        /* name */
         false,                 /* partial_inplace */
-        0,                     /* src_mask */
+        0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -630,7 +633,7 @@ static reloc_howto_type elf_mips_howto_table[] =
         bfd_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL16",       /* name */
         false,                 /* partial_inplace */
-        0,                     /* src_mask */
+        0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1890,35 +1893,44 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
 
 /* Given a MIPS Elf32_Internal_Rel, fill in an arelent structure.  */
 
-static void
-mips_info_to_howto_rel (abfd, cache_ptr, dst)
-     bfd *abfd;
-     arelent *cache_ptr;
-     Elf32_Internal_Rel *dst;
+static reloc_howto_type *
+mips_rtype_to_howto (r_type)
+     unsigned int r_type;
 {
-  unsigned int r_type;
-
-  r_type = ELF32_R_TYPE (dst->r_info);
   switch (r_type)
     {
     case R_MIPS16_26:
-      cache_ptr->howto = &elf_mips16_jump_howto;
+      return &elf_mips16_jump_howto;
       break;
     case R_MIPS16_GPREL:
-      cache_ptr->howto = &elf_mips16_gprel_howto;
+      return &elf_mips16_gprel_howto;
       break;
     case R_MIPS_GNU_VTINHERIT:
-      cache_ptr->howto = &elf_mips_gnu_vtinherit_howto;
+      return &elf_mips_gnu_vtinherit_howto;
       break;
     case R_MIPS_GNU_VTENTRY:
-      cache_ptr->howto = &elf_mips_gnu_vtentry_howto;
+      return &elf_mips_gnu_vtentry_howto;
       break;
 
     default:
       BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
-      cache_ptr->howto = &elf_mips_howto_table[r_type];
+      return &elf_mips_howto_table[r_type];
       break;
     }
+}
+
+/* Given a MIPS Elf32_Internal_Rel, fill in an arelent structure.  */
+
+static void
+mips_info_to_howto_rel (abfd, cache_ptr, dst)
+     bfd *abfd;
+     arelent *cache_ptr;
+     Elf32_Internal_Rel *dst;
+{
+  unsigned int r_type;
+
+  r_type = ELF32_R_TYPE (dst->r_info);
+  cache_ptr->howto = mips_rtype_to_howto (r_type);
 
   /* The addend for a GPREL16 or LITERAL relocation comes from the GP
      value for the object file.  We get the addend now, rather than
@@ -3865,7 +3877,7 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
          mips_elf_text_section.symbol = &mips_elf_text_symbol;
          mips_elf_text_section.symbol_ptr_ptr = &mips_elf_text_symbol_ptr;
          mips_elf_text_symbol.name = ".text";
-         mips_elf_text_symbol.flags = BSF_SECTION_SYM;
+         mips_elf_text_symbol.flags = BSF_SECTION_SYM | BSF_DYNAMIC;
          mips_elf_text_symbol.section = &mips_elf_text_section;
          mips_elf_text_symbol_ptr = &mips_elf_text_symbol;
          mips_elf_text_section_ptr = &mips_elf_text_section;
@@ -3889,7 +3901,7 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
          mips_elf_data_section.symbol = &mips_elf_data_symbol;
          mips_elf_data_section.symbol_ptr_ptr = &mips_elf_data_symbol_ptr;
          mips_elf_data_symbol.name = ".data";
-         mips_elf_data_symbol.flags = BSF_SECTION_SYM;
+         mips_elf_data_symbol.flags = BSF_SECTION_SYM | BSF_DYNAMIC;
          mips_elf_data_symbol.section = &mips_elf_data_section;
          mips_elf_data_symbol_ptr = &mips_elf_data_symbol;
          mips_elf_data_section_ptr = &mips_elf_data_section;
@@ -4330,7 +4342,7 @@ _bfd_mips_elf_final_link (abfd, info)
      generic size_dynamic_sections renumbered them out from under us.
      Rather than trying somehow to prevent the renumbering, just do
      the sort again.  */
-  if (elf_hash_table (info)->dynobj)
+  if (elf_hash_table (info)->dynamic_sections_created)
     {
       bfd *dynobj;
       asection *got;
@@ -4352,9 +4364,10 @@ _bfd_mips_elf_final_link (abfd, info)
       got = bfd_get_section_by_name (dynobj, ".got");
       g = (struct mips_got_info *) elf_section_data (got)->tdata;
 
-      BFD_ASSERT ((elf_hash_table (info)->dynsymcount
-                  - g->global_gotsym->dynindx)
-                 <= g->global_gotno);
+      if (g->global_gotsym != NULL)
+       BFD_ASSERT ((elf_hash_table (info)->dynsymcount
+                    - g->global_gotsym->dynindx)
+                   <= g->global_gotno);
     }
 
   /* On IRIX5, we omit the .options section.  On IRIX6, however, we
@@ -5525,7 +5538,11 @@ mips_elf_got16_entry (abfd, info, value)
   bfd_vma index;
   bfd_vma address;
 
-  value &= 0xffff0000;
+  /* Although the ABI says that it is "the high-order 16 bits" that we
+     want, it is really the %high value.  The complete value is
+     calculated with a `addiu' of a LO16 relocation, just as with a
+     HI16/LO16 pair.  */
+  value = mips_elf_high (value) << 16;
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
   /* Look to see if we already have an appropriate entry.  */
@@ -5539,7 +5556,7 @@ mips_elf_got16_entry (abfd, info, value)
       if ((address & 0xffff0000) == value)
        {
          /* This entry has the right high-order 16 bits.  */
-         index = MIPS_ELF_GOT_SIZE (abfd) * (entry - sgot->contents);
+         index = entry - sgot->contents;
          break;
        }
     }
@@ -5551,15 +5568,13 @@ mips_elf_got16_entry (abfd, info, value)
   return index;
 }
 
-/* Sets *ADDENDP to the addend for the first R_MIPS_LO16 relocation
-   found, beginning with RELOCATION.  RELEND is one-past-the-end of
-   the relocation table.  */
+/* Returns the first R_MIPS_LO16 relocation found, beginning with
+   RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
 
-static boolean
-mips_elf_next_lo16_addend (relocation, relend, addendp)
+static const Elf_Internal_Rela *
+mips_elf_next_lo16_relocation (relocation, relend)
      const Elf_Internal_Rela *relocation;
      const Elf_Internal_Rela *relend;
-     bfd_vma *addendp;
 {
   /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
      immediately following.  However, for the IRIX6 ABI, the next
@@ -5570,32 +5585,31 @@ mips_elf_next_lo16_addend (relocation, relend, addendp)
   while (relocation < relend)
     {
       if (ELF32_R_TYPE (relocation->r_info) == R_MIPS_LO16)
-       {
-         *addendp = relocation->r_addend;
-         return true;
-       }
+       return relocation;
 
       ++relocation;
     }
 
   /* We didn't find it.  */
   bfd_set_error (bfd_error_bad_value);
-  return false;
+  return NULL;
 }
 
-/* Create a rel.dyn relocation for the dynamic linker to resolve.  The
-   relocatin is against the symbol with the dynamic symbol table index
-   DYNINDX.  REL is the original relocation, which is now being made
-   dynamic.  */
+/* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
+   is the original relocation, which is now being transformed into a
+   dyanmic relocation.  The ADDENDP is adjusted if necessary; the
+   caller should store the result in place of the original addend.  */
 
-static unsigned int
-mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
-                                   addend, input_section)
+static boolean
+mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
+                                   symbol, addendp, input_section)
      bfd *output_bfd;
      struct bfd_link_info *info;
      const Elf_Internal_Rela *rel;
-     long dynindx;
-     bfd_vma addend;
+     struct mips_elf_link_hash_entry *h;
+     asection *sec;
+     bfd_vma symbol;
+     bfd_vma *addendp;
      asection *input_section;
 {
   Elf_Internal_Rel outrel;
@@ -5613,36 +5627,94 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
 
   skip = false;
 
-  /* The symbol for the relocation is the same as it was for the
-     original relocation.  */
-  outrel.r_info = ELF32_R_INFO (dynindx, R_MIPS_REL32);
-
-  /* The offset for the dynamic relocation is the same as for the
-     original relocation, adjusted by the offset at which the original
-     section is output.  */
+  /* We begin by assuming that the offset for the dynamic relocation
+     is the same as for the original relocation.  We'll adjust this
+     later to reflect the correct output offsets.  */
   if (elf_section_data (input_section)->stab_info == NULL)
     outrel.r_offset = rel->r_offset;
   else
     {
-      bfd_vma off;
-
-      off = (_bfd_stab_section_offset
-            (output_bfd, &elf_hash_table (info)->stab_info,
-             input_section,
-             &elf_section_data (input_section)->stab_info,
-             rel->r_offset));
-      if (off == (bfd_vma) -1)
+      /* Except that in a stab section things are more complex.
+        Because we compress stab information, the offset given in the
+        relocation may not be the one we want; we must let the stabs
+        machinery tell us the offset.  */
+      outrel.r_offset 
+       = (_bfd_stab_section_offset
+          (output_bfd, &elf_hash_table (info)->stab_info,
+           input_section,
+           &elf_section_data (input_section)->stab_info,
+           rel->r_offset));
+      /* If we didn't need the relocation at all, this value will be
+        -1.  */
+      if (outrel.r_offset == (bfd_vma) -1)
        skip = true;
-      outrel.r_offset = off;
     }
-  outrel.r_offset += (input_section->output_section->vma
-                     + input_section->output_offset);
 
   /* If we've decided to skip this relocation, just output an emtpy
-     record.  */
+     record.  Note that R_MIPS_NONE == 0, so that this call to memset
+     is a way of setting R_TYPE to R_MIPS_NONE.  */
   if (skip)
     memset (&outrel, 0, sizeof (outrel));
+  else
+    {
+      long indx;
+      bfd_vma section_offset;
+
+      /* We must now calculate the dynamic symbol table index to use
+        in the relocation.  */
+      if (h != NULL
+         && (! info->symbolic || (h->root.elf_link_hash_flags
+                                  & ELF_LINK_HASH_DEF_REGULAR) == 0))
+       {
+         indx = h->root.dynindx;
+         BFD_ASSERT (indx != -1);
+       }
+      else
+       {
+         if (sec != NULL && bfd_is_abs_section (sec))
+           indx = 0;
+         else if (sec == NULL || sec->owner == NULL)
+           {
+             bfd_set_error (bfd_error_bad_value);
+             return false;
+           }
+         else
+           {
+             indx = elf_section_data (sec->output_section)->dynindx;
+             if (indx == 0)
+               abort ();
+           }
+
+         /* Figure out how far the target of the relocation is from
+            the beginning of its section.  */
+         section_offset = symbol - sec->output_section->vma;
+         /* The relocation we're building is section-relative.
+            Therefore, the original addend must be adjusted by the
+            section offset.  */
+         *addendp += symbol - sec->output_section->vma;
+         /* Now, the relocation is just against the section.  */
+         symbol = sec->output_section->vma;
+       }
+      
+      /* If the relocation was previously an absolute relocation, we
+        must adjust it by the value we give it in the dynamic symbol
+        table.  */
+      if (r_type != R_MIPS_REL32)
+       *addendp += symbol;
+
+      /* The relocation is always an REL32 relocation because we don't
+        know where the shared library will wind up at load-time.  */
+      outrel.r_info = ELF32_R_INFO (indx, R_MIPS_REL32);
+
+      /* Adjust the output offset of the relocation to reference the
+        correct location in the output file.  */
+      outrel.r_offset += (input_section->output_section->vma
+                         + input_section->output_offset);
+    }
 
+  /* Put the relocation back out.  We have to use the special
+     relocation outputter in the 64-bit case since the 64-bit
+     relocation format is non-standard.  */
   if (ABI_64_P (output_bfd))
     {
       (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
@@ -5655,6 +5727,15 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
                              (((Elf32_External_Rel *)
                                sreloc->contents)
                               + sreloc->reloc_count));
+
+  /* Record the index of the first relocation referencing H.  This
+     information is later emitted in the .msym section.  */
+  if (h != NULL
+      && (h->min_dyn_reloc_index == 0 
+         || sreloc->reloc_count < h->min_dyn_reloc_index))
+    h->min_dyn_reloc_index = sreloc->reloc_count;
+
+  /* We've now added another relocation.  */
   ++sreloc->reloc_count;
 
   /* Make sure the output section is writable.  The dynamic linker
@@ -5681,7 +5762,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
          else
            mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
          mips_elf_set_cr_dist2to (cptrel, 0);
-         cptrel.konst = addend;
+         cptrel.konst = *addendp;
 
          cr = (scpt->contents
                + sizeof (Elf32_External_compact_rel));
@@ -5692,7 +5773,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
        }
     }
 
-  return sreloc->reloc_count - 1;
+  return true;
 }
 
 /* Calculate the value produced by the RELOCATION (which comes from
@@ -5859,6 +5940,25 @@ mips_elf_calculate_relocation (abfd,
          else
            symbol = h->root.root.u.def.value;
        }
+      else if (h->root.root.type == bfd_link_hash_undefweak)
+       /* We allow relocations against undefined weak symbols, giving
+          it the value zero, so that you can undefined weak functions
+          and check to see if they exist by looking at their
+          addresses.  */
+       symbol = 0;
+      else if (info->shared && !info->symbolic && !info->no_undefined)
+       symbol = 0;
+      else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0)
+       {
+         /* If this is a dynamic link, we should have created a
+            _DYNAMIC_LINK symbol in mips_elf_create_dynamic_sections.
+            Otherwise, we should define the symbol with a value of 0.
+            FIXME: It should probably get into the symbol table
+            somehow as well.  */
+         BFD_ASSERT (! info->shared);
+         BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
+         symbol = 0;
+       }
       else
        {
          (*info->callbacks->undefined_symbol)
@@ -5938,19 +6038,24 @@ mips_elf_calculate_relocation (abfd,
   switch (r_type)
     {
     case R_MIPS_CALL16:
+    case R_MIPS_GOT16:
     case R_MIPS_GOT_DISP:
     case R_MIPS_GOT_HI16:
     case R_MIPS_CALL_HI16:
     case R_MIPS_GOT_LO16:
     case R_MIPS_CALL_LO16:
       /* Find the index into the GOT where this value is located.  */
-      if (h)
+      if (!local_p)
        {
          BFD_ASSERT (addend == 0);
          g = mips_elf_global_got_index 
            (elf_hash_table (info)->dynobj,
             (struct elf_link_hash_entry*) h);
        }
+      else if (r_type == R_MIPS_GOT16)
+       /* There's no need to create a local GOT entry here; the
+          calculation for a local GOT16 entry does not involve G.  */
+       break;
       else
        {
          g = mips_elf_local_got_index (abfd, info, symbol + addend);
@@ -5989,27 +6094,28 @@ mips_elf_calculate_relocation (abfd,
     case R_MIPS_32:
     case R_MIPS_REL32:
     case R_MIPS_64:
-      /* If we're creating a shared library, or this relocation is
-        against a symbol in a shared library, then we can't know
-        where the symbol will end up.  So, we create a relocation
-        record in the output, and leave the job up to the dynamic
-        linker.  */
-      if (info->shared || !sec->output_section)
+      if ((info->shared
+          || (elf_hash_table (info)->dynamic_sections_created
+              && h != NULL
+              && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+                  == 0)))
+         && (input_section->flags & SEC_ALLOC) != 0)
        {
-         unsigned int reloc_index;
-
-         BFD_ASSERT (h != NULL);
-         reloc_index 
-           = mips_elf_create_dynamic_relocation (abfd, 
-                                                 info, 
-                                                 relocation,
-                                                 h->root.dynindx,
-                                                 addend,
-                                                 input_section);
-         if (h->min_dyn_reloc_index == 0
-             || reloc_index < h->min_dyn_reloc_index)
-           h->min_dyn_reloc_index = reloc_index;
-         value = symbol + addend;
+         /* If we're creating a shared library, or this relocation is
+            against a symbol in a shared library, then we can't know
+            where the symbol will end up.  So, we create a relocation
+            record in the output, and leave the job up to the dynamic
+            linker.  */
+         value = addend;
+         if (!mips_elf_create_dynamic_relocation (abfd, 
+                                                  info, 
+                                                  relocation,
+                                                  h,
+                                                  sec,
+                                                  symbol,
+                                                  &value,
+                                                  input_section))
+           return false;
        }
       else
        {
@@ -6460,7 +6566,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
           stored value is sign-extended to 64 bits.  */
        howto = elf_mips_howto_table + R_MIPS_32;
       else
-       howto = elf_mips_howto_table + r_type;
+       howto = mips_rtype_to_howto (r_type);
 
       if (!use_saved_addend_p)
        {
@@ -6497,13 +6603,31 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      && mips_elf_local_relocation_p (input_bfd, rel,
                                                      local_sections)))
                {
-                 /* Scan ahead to find a matching R_MIPS_LO16
-                    relocation.  */
                  bfd_vma l;
-                 
-                 if (!mips_elf_next_lo16_addend (rel, relend, &l))
+                 const Elf_Internal_Rela *lo16_relocation;
+                 reloc_howto_type *lo16_howto;
+
+                 /* The combined value is the sum of the HI16 addend,
+                    left-shifted by sixteen bits, and the LO16
+                    addend, sign extended.  (Usually, the code does
+                    a `lui' of the HI16 value, and then an `addiu' of
+                    the LO16 value.)  
+
+                    Scan ahead to find a matching R_MIPS_LO16
+                    relocation.  */
+                 lo16_relocation 
+                   = mips_elf_next_lo16_relocation (rel, relend); 
+                 if (lo16_relocation == NULL)
                    return false;
 
+                 /* Obtain the addend kept there.  */
+                 lo16_howto = mips_rtype_to_howto (R_MIPS_LO16);
+                 l = mips_elf_obtain_contents (lo16_howto,
+                                               lo16_relocation,
+                                               input_bfd, contents);
+                 l &= lo16_howto->src_mask;
+                 l = mips_elf_sign_extend (l, 16);
+
                  /* Save the high-order bit for later.  When we
                     encounter the R_MIPS_LO16 relocation we will need
                     them again.  */
@@ -6512,7 +6636,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  last_hi16_addend_valid_p = true;
 
                  /* Compute the combined addend.  */
-                 addend |= l;
+                 addend += l;
                }
              else if (r_type == R_MIPS_LO16) 
                {
@@ -6554,23 +6678,34 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            /* There's nothing to do for non-local relocations.  */
            continue;
 
-         r_symndx = ELF32_R_SYM (rel->r_info);
-         sym = local_syms + r_symndx;
-         if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-           /* Adjust the addend appropriately.  */
-           addend += local_sections[r_symndx]->output_offset;
-         
          if (r_type == R_MIPS16_GPREL 
              || r_type == R_MIPS_GPREL16
              || r_type == R_MIPS_GPREL32)
            addend -= (_bfd_get_gp_value (output_bfd)
                       - _bfd_get_gp_value (input_bfd));
+         else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26)
+           /* The addend is stored without its two least
+              significant bits (which are always zero.)  In a
+              non-relocateable link, calculate_relocation will do
+              this shift; here, we must do it ourselves.  */
+           addend <<= 2;
 
+         r_symndx = ELF32_R_SYM (rel->r_info);
+         sym = local_syms + r_symndx;
+         if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           /* Adjust the addend appropriately.  */
+           addend += local_sections[r_symndx]->output_offset;
+         
          /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
             then we only want to write out the high-order 16 bits.
             The subsequent R_MIPS_LO16 will handle the low-order bits.  */
          if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16)
-           addend >>= 16;
+           addend = mips_elf_high (addend);
+         /* If the relocation is for an R_MIPS_26 relocation, then
+            the two low-order bits are not stored in the object file;
+            they are implicitly zero.  */
+         else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26)
+           addend >>= 2;
 
          if (rela_relocation_p)
            /* If this is a RELA relocation, just update the addend.
@@ -6600,7 +6735,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
         for the next.  */
       if (rel + 1 < relend 
          && rel->r_offset == rel[1].r_offset
-         && r_type != R_MIPS_NONE)
+         && ELF32_R_TYPE (rel[1].r_info) != R_MIPS_NONE)
        use_saved_addend_p = true;
       else
        use_saved_addend_p = false;
@@ -6625,8 +6760,10 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
        case bfd_reloc_undefined:
          /* mips_elf_calculate_relocation already called the
-             undefined_symbol callback.  */
-         break;
+             undefined_symbol callback.  There's no real point in
+            trying to perform the relocation at this point, so we
+            just skip ahead to the next relocation.  */
+         continue;
 
        case bfd_reloc_notsupported:
          abort ();
@@ -7322,11 +7459,12 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                 || r_type == R_MIPS_GOT_DISP))
        {
          /* We may need a local GOT entry for this relocation.  We
-            don't count R_MIPS_HI16 or R_MIPS_GOT16 relocations
-            because they are always followed by a R_MIPS_LO16
-            relocation for the value.  We don't R_MIPS_GOT_PAGE
-            because we can estimate the maximum number of pages
-            needed by looking at the size of the segment.
+            don't count R_MIPS_GOT_PAGE because we can estimate the
+            maximum number of pages needed by looking at the size of
+            the segment.  Similar comments apply to R_MIPS_GOT16.  We
+            don't count R_MIPS_GOT_HI16, or R_MIPS_CALL_HI16 because
+            these are always followed by an R_MIPS_GOT_LO16 or
+            R_MIPS_CALL_LO16.
 
             This estimation is very conservative since we can merge
             duplicate entries in the GOT.  In order to be less
@@ -7351,16 +7489,18 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
        case R_MIPS_CALL_HI16:
        case R_MIPS_CALL_LO16:
-         /* This symbol requires a global offset table entry.  */
-         if (!mips_elf_record_global_got_symbol (h, info, g))
-           return false;
-
-         /* We need a stub, not a plt entry for the undefined
-            function.  But we record it as if it needs plt.  See
-            elf_adjust_dynamic_symbol in elflink.h.  */
-         h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
-         h->type = STT_FUNC;
+         if (h != NULL)
+           {
+             /* This symbol requires a global offset table entry.  */
+             if (!mips_elf_record_global_got_symbol (h, info, g))
+               return false;
 
+             /* We need a stub, not a plt entry for the undefined
+                function.  But we record it as if it needs plt.  See
+                elf_adjust_dynamic_symbol in elflink.h.  */
+             h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+             h->type = STT_FUNC;
+           }
          break;
 
        case R_MIPS_GOT16:
@@ -7417,9 +7557,10 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
             
              /* Even though we don't directly need a GOT entry for
                 this symbol, a symbol must have a dynamic symbol
-                table index greater that DT_GOTSYM if there are
+                table index greater that DT_MIPS_GOTSYM if there are
                 dynamic relocations against it.  */
-             if (!mips_elf_record_global_got_symbol (h, info, g))
+             if (h != NULL
+                 && !mips_elf_record_global_got_symbol (h, info, g))
                return false;
            }
 
@@ -7752,7 +7893,7 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
   bfd *dynobj;
   asection *s;
   boolean reltext;
-  struct mips_got_info *g;
+  struct mips_got_info *g = NULL;
 
   dynobj = elf_hash_table (info)->dynobj;
   BFD_ASSERT (dynobj != NULL);
@@ -7862,8 +8003,14 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
          loadable_size += MIPS_FUNCTION_STUB_SIZE;
 
          /* Assume there are two loadable segments consisting of
-            contiguous sections.  Is 5 enough? */
+            contiguous sections.  Is 5 enough?  */
          local_gotno = (loadable_size >> 16) + 5;
+         if (IRIX_COMPAT (output_bfd) == ict_irix6)
+           /* It's possible we will need GOT_PAGE entries as well as
+              GOT16 entries.  Often, these will be able to share GOT
+              entries, but not always.  */
+           local_gotno *= 2;
+
          g->local_gotno += local_gotno;
          s->_raw_size += local_gotno * MIPS_ELF_GOT_SIZE (dynobj);
 
@@ -7875,7 +8022,12 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
          if (!mips_elf_sort_hash_table (info, 1))
            return false;
 
-         i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
+         if (g->global_gotsym != NULL)
+           i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
+         else
+           /* If there are no global symbols, or none requiring
+              relocations, then GLOBAL_GOTSYM will be NULL.  */
+           i = 0;
          g->global_gotno = i;
          s->_raw_size += i * MIPS_ELF_GOT_SIZE (dynobj);
        }
@@ -8165,7 +8317,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 
   /* Run through the global symbol table, creating GOT entries for all
      the symbols that need them.  */
-  if (h->dynindx >= g->global_gotsym->dynindx)
+  if (g->global_gotsym != NULL
+      && h->dynindx >= g->global_gotsym->dynindx)
     {
       bfd_vma offset;
       bfd_vma value;
@@ -8411,6 +8564,23 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
              dyn.d_un.d_val = g->local_gotno;
              break;
 
+           case DT_MIPS_UNREFEXTNO:
+             /* The index into the dynamic symbol table which is the
+                entry of the first external symbol that is not
+                referenced within the same object.  */
+             dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
+             break;
+
+           case DT_MIPS_GOTSYM:
+             if (g->global_gotsym)
+               {
+                 dyn.d_un.d_val = g->global_gotsym->dynindx;
+                 break;
+               }
+             /* In case if we don't have global got symbols we default
+                to setting DT_MIPS_GOTSYM to the same value as
+                DT_MIPS_SYMTABNO, so we just fall through.  */
+
            case DT_MIPS_SYMTABNO:
              name = ".dynsym";
              elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
@@ -8423,17 +8593,6 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
                dyn.d_un.d_val = s->_raw_size / elemsize;
              break;
 
-           case DT_MIPS_UNREFEXTNO:
-             /* The index into the dynamic symbol table which is the
-                entry of the first external symbol that is not
-                referenced within the same object.  */
-             dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
-             break;
-
-           case DT_MIPS_GOTSYM:
-             dyn.d_un.d_val = g->global_gotsym->dynindx;
-             break;
-
            case DT_MIPS_HIPAGENO:
              dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO;
              break;
This page took 0.032362 seconds and 4 git commands to generate.