* dwarf2.c (read_attribute): Support DW_FORM_ref8.
authorMark Mitchell <mark@codesourcery.com>
Mon, 12 Jul 1999 17:15:34 +0000 (17:15 +0000)
committerMark Mitchell <mark@codesourcery.com>
Mon, 12 Jul 1999 17:15:34 +0000 (17:15 +0000)
* elf32-mips.c (mips_elf_link_hash_entry): Change mips_32_relocs
to possibly_dynamic_relocs.  Adjust usage throughout code.
(elf_mips_howto_table): Handle R_MIPS_64 correctly.
(elf_mips_ctor64_howto): Likewise.
(mips_elf_calculate_relocation): Handle R_MIPS_64 like R_MIPS_32.
Adjust indentation.
(mips_elf_relocate_section): Handle R_MIPS_64 in 32-bit mode.
(_bfd_mips_elf_check_relocs): Handle R_MIPS_64 like R_MIPS_32.
Use MIPS_ELF_GOT_SIZE to calculate the size of GOT entries.
* elf64-mips.c (elf_backend_may_use_rel_p): Define.

bfd/ChangeLog
bfd/elf32-mips.c

index 7bec39873df8007d4cddafa814e595a68a8cc1ac..c274a440df1ab26c52fdcf52e23e5933b7f2e6ec 100644 (file)
@@ -1,3 +1,17 @@
+1999-07-12  Mark Mitchell  <mark@codesourcery.com>
+
+       * dwarf2.c (read_attribute): Support DW_FORM_ref8.
+       * elf32-mips.c (mips_elf_link_hash_entry): Change mips_32_relocs
+       to possibly_dynamic_relocs.  Adjust usage throughout code.
+       (elf_mips_howto_table): Handle R_MIPS_64 correctly.
+       (elf_mips_ctor64_howto): Likewise.
+       (mips_elf_calculate_relocation): Handle R_MIPS_64 like R_MIPS_32.
+       Adjust indentation.
+       (mips_elf_relocate_section): Handle R_MIPS_64 in 32-bit mode.
+       (_bfd_mips_elf_check_relocs): Handle R_MIPS_64 like R_MIPS_32.
+       Use MIPS_ELF_GOT_SIZE to calculate the size of GOT entries.
+       * elf64-mips.c (elf_backend_may_use_rel_p): Define.
+
 1999-07-12  Ian Lance Taylor  <ian@zembu.com>
 
        * Makefile.am: Rebuild dependencies.
index c93af0b16cb7bb896b37bd192f3570af780efb4a..9d7a07404e9d98d4888978c706815b2faf759fe8 100644 (file)
@@ -67,8 +67,9 @@ struct mips_elf_link_hash_entry
   /* External symbol information.  */
   EXTR esym;
 
-  /* Number of MIPS_32 or MIPS_REL32 relocs against this symbol.  */
-  unsigned int mips_32_relocs;
+  /* Number of R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 relocs against
+     this symbol.  */ 
+  unsigned int possibly_dynamic_relocs;
 
   /* The index of the first dynamic relocation (in the .rel.dyn
      section) against this symbol.  */
@@ -678,22 +679,19 @@ static reloc_howto_type elf_mips_howto_table[] =
         0x000007c4,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* A 64 bit relocation.  This is used in 32 bit ELF when addresses
-     are 64 bits long; the upper 32 bits are simply a sign extension.
-     The fields of the howto should be the same as for R_MIPS_32,
-     other than the type, name, and special_function.  */
+  /* A 64 bit relocation.  */
   HOWTO (R_MIPS_64,            /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         mips32_64bit_reloc,    /* special_function */
         "R_MIPS_64",           /* name */
         true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
         false),                /* pcrel_offset */
 
   /* Displacement in the global offset table.  */
@@ -3766,7 +3764,7 @@ mips_elf_link_hash_newfunc (entry, table, string)
       /* We use -2 as a marker to indicate that the information has
         not been set.  -1 means there is no associated ifd.  */
       ret->esym.ifd = -2;
-      ret->mips_32_relocs = 0;
+      ret->possibly_dynamic_relocs = 0;
       ret->min_dyn_reloc_index = 0;
       ret->fn_stub = NULL;
       ret->need_fn_stub = false;
@@ -5850,6 +5848,7 @@ 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
@@ -5862,11 +5861,11 @@ mips_elf_calculate_relocation (abfd,
          BFD_ASSERT (h != NULL);
          reloc_index 
            = mips_elf_create_dynamic_relocation (abfd, 
-                                                  info, 
-                                                  relocation,
-                                                  h->root.dynindx,
-                                                  addend,
-                                                  input_section);
+                                                 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;
@@ -5874,7 +5873,7 @@ mips_elf_calculate_relocation (abfd,
        }
       else
        {
-         if (r_type == R_MIPS_32)
+         if (r_type != R_MIPS_REL32)
            value = symbol + addend;
          else
            value = addend;
@@ -5975,10 +5974,6 @@ mips_elf_calculate_relocation (abfd,
       value = g & howto->dst_mask;
       break;
 
-    case R_MIPS_64:
-      value = (symbol + addend) & howto->dst_mask;
-      break;
-
     case R_MIPS_GOT_PAGE:
       value = mips_elf_got_page (abfd, info, symbol + addend, NULL);
       if (value == (bfd_vma) -1)
@@ -6178,7 +6173,17 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       reloc_howto_type *howto;
 
       /* Find the relocation howto for this relocation.  */
-      howto = elf_mips_howto_table + ELF32_R_TYPE (rel->r_info);
+      if (ELF32_R_TYPE (rel->r_info) == 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;
+      else
+       howto = elf_mips_howto_table + ELF32_R_TYPE (rel->r_info);
 
       if (!use_saved_addend_p)
        {
@@ -6303,6 +6308,56 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
        }
 
+      if (ELF32_R_TYPE (rel->r_info) == R_MIPS_64
+         && !ABI_64_P (output_bfd))
+       /* See the comment above about using R_MIPS_64 in the 32-bit
+          ABI.  Until now, we've been using the HOWTO for R_MIPS_32;
+          that calculated the right value.  Now, however, we
+          sign-extend the 32-bit result to 64-bits, and store it as a
+          64-bit value.  We are especially generous here in that we
+          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;
+
+         if (value & 0x80000000)
+           sign_bits = 0xffffffff;
+         else
+           sign_bits = 0;
+
+         /* If only a 32-bit VMA is available do two separate
+            stores.  */
+         if (bfd_big_endian (input_bfd))
+           {
+             /* Store the sign-bits (which are most significant)
+                first.  */
+             low_bits = sign_bits;
+             high_bits = value;
+           }
+         else
+           {
+             low_bits = value;
+             high_bits = sign_bits;
+           }
+         bfd_put_32 (input_bfd, low_bits, 
+                     contents + rel->r_offset);
+         bfd_put_32 (input_bfd, high_bits, 
+                     contents + rel->r_offset + 4);
+         continue;
+#endif /* !BFD64 */
+       }
+
       /* Actually perform the relocation.  */
       mips_elf_perform_relocation (howto, rel, value, input_bfd, 
                                   contents);
@@ -6891,6 +6946,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
            case R_MIPS_32:
            case R_MIPS_REL32:
+           case R_MIPS_64:
              if (dynobj == NULL
                  && (info->shared || h != NULL)
                  && (sec->flags & SEC_ALLOC) != 0)
@@ -6918,7 +6974,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
             conservative, we could actually build the GOT here,
             rather than in relocate_section.  */
          g->local_gotno++;
-         sgot->_raw_size += 4;
+         sgot->_raw_size += MIPS_ELF_GOT_SIZE (dynobj);
        }
 
       switch (r_type)
@@ -6959,6 +7015,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
        case R_MIPS_32:
        case R_MIPS_REL32:
+       case R_MIPS_64:
          if ((info->shared || h != NULL)
              && (sec->flags & SEC_ALLOC) != 0)
            {
@@ -6996,7 +7053,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                  /* We only need to copy this reloc if the symbol is
                      defined in a dynamic object.  */
                  hmips = (struct mips_elf_link_hash_entry *) h;
-                 ++hmips->mips_32_relocs;
+                 ++hmips->possibly_dynamic_relocs;
                }
             
              /* Even though we don't directly need a GOT entry for
@@ -7189,9 +7246,10 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
      file.  */
   hmips = (struct mips_elf_link_hash_entry *) h;
   if (! info->relocateable
-      && hmips->mips_32_relocs != 0
+      && hmips->possibly_dynamic_relocs != 0
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    mips_elf_allocate_dynamic_relocations (dynobj, hmips->mips_32_relocs);
+    mips_elf_allocate_dynamic_relocations (dynobj, 
+                                          hmips->possibly_dynamic_relocs);
 
   /* For a function, create a stub, if needed. */
   if (h->type == STT_FUNC