2000-02-14 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index f18f1fd03ac045537b3cc3bdf10ff655095d8a22..d9832b67b94066ec617398fc06e8a23c59394071 100644 (file)
@@ -124,14 +124,6 @@ static boolean mips_elf_is_local_label_name
 static struct bfd_hash_entry *mips_elf_link_hash_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
 static int gptab_compare PARAMS ((const void *, const void *));
-static void mips_elf_relocate_hi16
-  PARAMS ((bfd *, Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_byte *,
-          bfd_vma));
-static boolean mips_elf_relocate_got_local
-  PARAMS ((bfd *, bfd *, asection *, Elf_Internal_Rela *,
-          Elf_Internal_Rela *, bfd_byte *, bfd_vma));
-static void mips_elf_relocate_global_got
-   PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
 static bfd_reloc_status_type mips16_jump_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips16_gprel_reloc
@@ -5015,124 +5007,6 @@ _bfd_mips_elf_final_link (abfd, info)
   return true;
 }
 
-/* Handle a MIPS ELF HI16 reloc.  */
-
-static void
-mips_elf_relocate_hi16 (input_bfd, relhi, rello, contents, addend)
-     bfd *input_bfd;
-     Elf_Internal_Rela *relhi;
-     Elf_Internal_Rela *rello;
-     bfd_byte *contents;
-     bfd_vma addend;
-{
-  bfd_vma insn;
-  bfd_vma addlo;
-
-  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
-
-  addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
-  addlo &= 0xffff;
-
-  addend += ((insn & 0xffff) << 16) + addlo;
-
-  if ((addlo & 0x8000) != 0)
-    addend -= 0x10000;
-  if ((addend & 0x8000) != 0)
-    addend += 0x10000;
-
-  bfd_put_32 (input_bfd,
-             (insn & 0xffff0000) | ((addend >> 16) & 0xffff),
-             contents + relhi->r_offset);
-}
-
-/* Handle a MIPS ELF local GOT16 reloc.  */
-
-static boolean
-mips_elf_relocate_got_local (output_bfd, input_bfd, sgot, relhi, rello,
-                            contents, addend)
-     bfd *output_bfd;
-     bfd *input_bfd;
-     asection *sgot;
-     Elf_Internal_Rela *relhi;
-     Elf_Internal_Rela *rello;
-     bfd_byte *contents;
-     bfd_vma addend;
-{
-  unsigned int assigned_gotno;
-  unsigned int i;
-  bfd_vma insn;
-  bfd_vma addlo;
-  bfd_vma address;
-  bfd_vma hipage;
-  bfd_byte *got_contents;
-  struct mips_got_info *g;
-
-  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
-
-  addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
-  addlo &= 0xffff;
-
-  addend += ((insn & 0xffff) << 16) + addlo;
-
-  if ((addlo & 0x8000) != 0)
-    addend -= 0x10000;
-  if ((addend & 0x8000) != 0)
-    addend += 0x10000;
-
-  /* Get a got entry representing requested hipage.  */
-  BFD_ASSERT (elf_section_data (sgot) != NULL);
-  g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
-  BFD_ASSERT (g != NULL);
-
-  assigned_gotno = g->assigned_gotno;
-  got_contents = sgot->contents;
-  hipage = addend & 0xffff0000;
-
-  for (i = MIPS_RESERVED_GOTNO; i < assigned_gotno; i++)
-    {
-      address = bfd_get_32 (input_bfd, got_contents + i * 4);
-      if (hipage == (address & 0xffff0000))
-       break;
-    }
-
-  if (i == assigned_gotno)
-    {
-      if (assigned_gotno >= g->local_gotno)
-       {
-         (*_bfd_error_handler)
-           (_("more got entries are needed for hipage relocations"));
-         bfd_set_error (bfd_error_bad_value);
-         return false;
-       }
-
-      bfd_put_32 (input_bfd, hipage, got_contents + assigned_gotno * 4);
-      ++g->assigned_gotno;
-    }
-
-  i = - ELF_MIPS_GP_OFFSET (output_bfd) + i * 4;
-  bfd_put_32 (input_bfd, (insn & 0xffff0000) | (i & 0xffff),
-             contents + relhi->r_offset);
-
-  return true;
-}
-
-/* Handle MIPS ELF CALL16 reloc and global GOT16 reloc.  */
-
-static void
-mips_elf_relocate_global_got (input_bfd, rel, contents, offset)
-     bfd *input_bfd;
-     Elf_Internal_Rela *rel;
-     bfd_byte *contents;
-     bfd_vma offset;
-{
-  bfd_vma insn;
-
-  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-  bfd_put_32 (input_bfd,
-             (insn & 0xffff0000) | (offset & 0xffff),
-             contents + rel->r_offset);
-}
-
 /* Returns the GOT section for ABFD.  */
 
 static asection *
@@ -5195,7 +5069,7 @@ mips_elf_sign_extend (value, bits)
      bfd_vma value;
      int bits;
 {
-  if (value & (1 << (bits - 1)))
+  if (value & ((bfd_vma)1 << (bits - 1)))
     /* VALUE is negative.  */
     value |= ((bfd_vma) - 1) << bits;      
   
@@ -5254,7 +5128,7 @@ mips_elf_highest (value)
      bfd_vma value ATTRIBUTE_UNUSED;
 {
 #ifdef BFD64
-  return ((value + (bfd_vma) 0x800080008000) > 48) & 0xffff;
+  return ((value + (bfd_vma) 0x800080008000) >> 48) & 0xffff;
 #else
   abort ();
   return (bfd_vma) -1;
@@ -6072,6 +5946,7 @@ mips_elf_calculate_relocation (abfd,
     case R_MIPS_LO16:
     case R_MIPS_GPREL16:
     case R_MIPS_GPREL32:
+    case R_MIPS_LITERAL:
       gp0 = _bfd_get_gp_value (input_bfd);
       gp = _bfd_get_gp_value (abfd);
       break;
@@ -6228,6 +6103,7 @@ mips_elf_calculate_relocation (abfd,
 
     case R_MIPS_PC16:
       value = mips_elf_sign_extend (addend, 16) + symbol - p;
+      value = (bfd_vma) ((bfd_signed_vma) value / 4);
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
@@ -6538,9 +6414,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *relend;
   bfd_vma addend;
-  bfd_vma last_hi16_addend;
   boolean use_saved_addend_p = false;
-  boolean last_hi16_addend_valid_p = false;
   struct elf_backend_data *bed;
 
   bed = get_elf_backend_data (output_bfd);
@@ -6558,13 +6432,20 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       /* Find the relocation howto for this relocation.  */
       if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
-       /* Some 32-bit code uses R_MIPS_64.  In particular, people use
-          64-bit code, but make sure all their addresses are in the 
-          lowermost or uppermost 32-bit section of the 64-bit address
-          space.  Thus, when they use an R_MIPS_64 they mean what is
-          usually meant by R_MIPS_32, with the exception that the
-          stored value is sign-extended to 64 bits.  */
-       howto = elf_mips_howto_table + R_MIPS_32;
+       {
+         /* Some 32-bit code uses R_MIPS_64.  In particular, people use
+            64-bit code, but make sure all their addresses are in the 
+            lowermost or uppermost 32-bit section of the 64-bit address
+            space.  Thus, when they use an R_MIPS_64 they mean what is
+            usually meant by R_MIPS_32, with the exception that the
+            stored value is sign-extended to 64 bits.  */
+         howto = elf_mips_howto_table + R_MIPS_32;
+
+         /* On big-endian systems, we need to lie about the position
+            of the reloc.  */
+         if (bfd_big_endian (input_bfd))
+             rel->r_offset += 4;
+       }
       else
        howto = mips_rtype_to_howto (r_type);
 
@@ -6628,26 +6509,11 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  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.  */
                  addend <<= 16;
-                 last_hi16_addend = addend;
-                 last_hi16_addend_valid_p = true;
 
                  /* Compute the combined addend.  */
                  addend += l;
                }
-             else if (r_type == R_MIPS_LO16) 
-               {
-                 /* Used the saved HI16 addend.  */
-                 if (!last_hi16_addend_valid_p)
-                   {
-                     bfd_set_error (bfd_error_bad_value);
-                     return false;
-                   }
-                 addend |= last_hi16_addend;
-               }
              else if (r_type == R_MIPS16_GPREL)
                {
                  /* The addend is scrambled in the object file.  See
@@ -6680,7 +6546,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          if (r_type == R_MIPS16_GPREL 
              || r_type == R_MIPS_GPREL16
-             || r_type == R_MIPS_GPREL32)
+             || r_type == R_MIPS_GPREL32
+             || r_type == R_MIPS_LITERAL)
            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)
@@ -6809,15 +6676,6 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
           go to extreme lengths to support this usage on systems with
           only a 32-bit VMA.  */
        {
-#ifdef BFD64
-         /* Just sign-extend the value, and then fall through to the
-            normal case, using the R_MIPS_64 howto.  That will store
-            the 64-bit value into a 64-bit area.  */
-         value = mips_elf_sign_extend (value, 64);
-         howto = elf_mips_howto_table + R_MIPS_64;
-#else /* !BFD64 */
-         /* In the 32-bit VMA case, we must handle sign-extension and
-            endianness manually.  */
          bfd_vma sign_bits;
          bfd_vma low_bits;
          bfd_vma high_bits;
@@ -6831,6 +6689,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             stores.  */
          if (bfd_big_endian (input_bfd))
            {
+             /* Undo what we did above.  */
+             rel->r_offset -= 4;
              /* Store the sign-bits (which are most significant)
                 first.  */
              low_bits = sign_bits;
@@ -6846,7 +6706,6 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          bfd_put_32 (input_bfd, high_bits, 
                      contents + rel->r_offset + 4);
          continue;
-#endif /* !BFD64 */
        }
 
       /* Actually perform the relocation.  */
@@ -7456,15 +7315,15 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
       if (!h && (r_type == R_MIPS_CALL_LO16
                 || r_type == R_MIPS_GOT_LO16
-                || r_type == R_MIPS_GOT_DISP
-                || r_type == R_MIPS_GOT16))
+                || r_type == R_MIPS_GOT_DISP))
        {
          /* We may need a local GOT entry for this relocation.  We
             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.  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.
+            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
@@ -8003,8 +7862,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);
 
@@ -8055,7 +7920,7 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
 
       if (strip)
        {
-         _bfd_strip_section_from_output (s);
+         _bfd_strip_section_from_output (info, s);
          continue;
        }
 
@@ -8945,6 +8810,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap =
 #define elf_backend_collect            true
 #define elf_backend_type_change_ok     true
 #define elf_backend_can_gc_sections    true
+#define elf_backend_sign_extend_vma    true
 #define elf_info_to_howto              mips_info_to_howto_rela
 #define elf_info_to_howto_rel          mips_info_to_howto_rel
 #define elf_backend_sym_is_global      mips_elf_sym_is_global
This page took 0.028262 seconds and 4 git commands to generate.