ELF/BFD: Hold the number of internal static relocs in `->reloc_count'
[deliverable/binutils-gdb.git] / bfd / elf64-mips.c
index eb7e1fba4b8fcf9352194dd0fede17be7d9a9049..84f2a3f8fcd7016f57a91d5c7571725bfaba1b25 100644 (file)
@@ -1,5 +1,5 @@
 /* MIPS-specific support for 64-bit ELF
-   Copyright (C) 1996-2014 Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
    Ian Lance Taylor, Cygnus Support
    Linker support added by Mark Mitchell, CodeSourcery, LLC.
    <mark@codesourcery.com>
@@ -86,14 +86,8 @@ static void mips_elf64_info_to_howto_rel
   (bfd *, arelent *, Elf_Internal_Rela *);
 static void mips_elf64_info_to_howto_rela
   (bfd *, arelent *, Elf_Internal_Rela *);
-static long mips_elf64_get_reloc_upper_bound
-  (bfd *, asection *);
-static long mips_elf64_canonicalize_reloc
-  (bfd *, asection *, arelent **, asymbol **);
 static long mips_elf64_get_dynamic_reloc_upper_bound
   (bfd *);
-static long mips_elf64_canonicalize_dynamic_reloc
-  (bfd *, arelent **, asymbol **);
 static bfd_boolean mips_elf64_slurp_one_reloc_table
   (bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, arelent *,
    asymbol **, bfd_boolean);
@@ -145,7 +139,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
   /* No relocation.  */
   HOWTO (R_MIPS_NONE,          /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -908,7 +902,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
   /* No relocation.  */
   HOWTO (R_MIPS_NONE,          /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1881,6 +1875,21 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] =
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
+
+  /* MIPS16 16-bit PC-relative branch offset.  */
+  HOWTO (R_MIPS16_PC16_S1,     /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_PC16_S1",    /* name */
+        TRUE,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        TRUE),                 /* pcrel_offset */
 };
 
 static reloc_howto_type mips16_elf64_howto_table_rela[] =
@@ -2082,6 +2091,21 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] =
         0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
+
+  /* MIPS16 16-bit PC-relative branch offset.  */
+  HOWTO (R_MIPS16_PC16_S1,     /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_PC16_S1",    /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        TRUE),                 /* pcrel_offset */
 };
 
 static reloc_howto_type micromips_elf64_howto_table_rel[] =
@@ -3415,7 +3439,8 @@ static const struct elf_reloc_map mips16_reloc_map[] =
     R_MIPS16_TLS_DTPREL_LO16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_TLS_GOTTPREL, R_MIPS16_TLS_GOTTPREL - R_MIPS16_min },
   { BFD_RELOC_MIPS16_TLS_TPREL_HI16, R_MIPS16_TLS_TPREL_HI16 - R_MIPS16_min },
-  { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min }
+  { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_16_PCREL_S1, R_MIPS16_PC16_S1 - R_MIPS16_min }
 };
 
 static const struct elf_reloc_map micromips_reloc_map[] =
@@ -3585,7 +3610,12 @@ mips_elf64_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p)
          else
            return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min];
        }
-      BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
+      if (r_type >= R_MIPS_max)
+       {
+         _bfd_error_handler (_("unrecognised MIPS reloc number: %d"), r_type);
+         bfd_set_error (bfd_error_bad_value);
+         r_type = R_MIPS_NONE;
+       }
       if (rela_p)
        return &mips_elf64_howto_table_rela[r_type];
       else
@@ -3615,88 +3645,20 @@ mips_elf64_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
    to three relocs, we must tell the user to allocate more space.  */
 
-static long
-mips_elf64_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
-{
-  return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
-}
-
 static long
 mips_elf64_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
   return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
 }
 
-/* We must also copy more relocations than the corresponding functions
-   in elf.c would, so the two following functions are slightly
-   modified from elf.c, that multiply the external relocation count by
-   3 to obtain the internal relocation count.  */
-
-static long
-mips_elf64_canonicalize_reloc (bfd *abfd, sec_ptr section,
-                              arelent **relptr, asymbol **symbols)
-{
-  arelent *tblptr;
-  unsigned int i;
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
-  if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
-    return -1;
-
-  tblptr = section->relocation;
-  for (i = 0; i < section->reloc_count * 3; i++)
-    *relptr++ = tblptr++;
-
-  *relptr = NULL;
-
-  return section->reloc_count * 3;
-}
-
-static long
-mips_elf64_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage,
-                                      asymbol **syms)
-{
-  bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
-  asection *s;
-  long ret;
-
-  if (elf_dynsymtab (abfd) == 0)
-    {
-      bfd_set_error (bfd_error_invalid_operation);
-      return -1;
-    }
-
-  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
-  ret = 0;
-  for (s = abfd->sections; s != NULL; s = s->next)
-    {
-      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
-         && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
-             || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
-       {
-         arelent *p;
-         long count, i;
-
-         if (! (*slurp_relocs) (abfd, s, syms, TRUE))
-           return -1;
-         count = s->size / elf_section_data (s)->this_hdr.sh_entsize * 3;
-         p = s->relocation;
-         for (i = 0; i < count; i++)
-           *storage++ = p++;
-         ret += count;
-       }
-    }
-
-  *storage = NULL;
-
-  return ret;
-}
-
 /* Read the relocations from one reloc section.  This is mostly copied
    from elfcode.h, except for the changes to expand one external
-   relocation to 3 internal ones.  We must unfortunately set
-   reloc_count to the number of external relocations, because a lot of
-   generic code seems to depend on this.  */
+   relocation to 3 internal ones.  To reduce processing effort we
+   could discard those R_MIPS_NONE relocations that occupy the second
+   and the third entry of a triplet, as `mips_elf64_write_rel' and
+   `mips_elf64_write_rela' recreate them in output automagically,
+   however that would also remove them from `objdump -r' output,
+   breaking a long-established tradition and likely confusing people.  */
 
 static bfd_boolean
 mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
@@ -3849,8 +3811,6 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
        }
     }
 
-  asect->reloc_count += (relent - relents) / 3;
-
   if (allocated != NULL)
     free (allocated);
 
@@ -3865,8 +3825,7 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
 /* Read the relocations.  On Irix 6, there can be two reloc sections
    associated with a single data section.  This is copied from
    elfcode.h as well, with changes as small as accounting for 3
-   internal relocs per external reloc and resetting reloc_count to
-   zero before processing the relocs of a section.  */
+   internal relocs per external reloc.  */
 
 static bfd_boolean
 mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect,
@@ -3894,7 +3853,7 @@ mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect,
       rel_hdr2 = d->rela.hdr;
       reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
 
-      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+      BFD_ASSERT (asect->reloc_count == 3 * (reloc_count + reloc_count2));
       BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
                  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
 
@@ -3920,9 +3879,6 @@ mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect,
   if (relents == NULL)
     return FALSE;
 
-  /* The slurp_one_reloc_table routine increments reloc_count.  */
-  asect->reloc_count = 0;
-
   if (rel_hdr != NULL
       && ! mips_elf64_slurp_one_reloc_table (abfd, asect,
                                             rel_hdr, reloc_count,
@@ -4431,6 +4387,7 @@ const struct elf_size_info mips_elf64_size_info =
 #define elf_backend_grok_psinfo                elf64_mips_grok_psinfo
 
 #define elf_backend_got_header_size    (8 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro      1
 
 /* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
    work better/work only in RELA, so we default to this.  */
@@ -4466,36 +4423,9 @@ const struct elf_size_info mips_elf64_size_info =
 #define bfd_elf64_bfd_print_private_bfd_data \
                                _bfd_mips_elf_print_private_bfd_data
 
-#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
-#define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc
 #define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
-#define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc
-#define bfd_elf64_bfd_relax_section     _bfd_mips_relax_section
 #define bfd_elf64_mkobject             _bfd_mips_elf_mkobject
 
-/* MIPS ELF64 archive functions.  */
-#define bfd_elf64_archive_functions
-extern bfd_boolean bfd_elf64_archive_slurp_armap
-  (bfd *);
-extern bfd_boolean bfd_elf64_archive_write_armap
-  (bfd *, unsigned int, struct orl *, unsigned int, int);
-#define bfd_elf64_archive_slurp_extended_name_table \
-                       _bfd_archive_coff_slurp_extended_name_table
-#define bfd_elf64_archive_construct_extended_name_table \
-                       _bfd_archive_coff_construct_extended_name_table
-#define bfd_elf64_archive_truncate_arname \
-                       _bfd_archive_coff_truncate_arname
-#define bfd_elf64_archive_read_ar_hdr  _bfd_archive_coff_read_ar_hdr
-#define bfd_elf64_archive_write_ar_hdr _bfd_archive_coff_write_ar_hdr
-#define bfd_elf64_archive_openr_next_archived_file \
-                       _bfd_archive_coff_openr_next_archived_file
-#define bfd_elf64_archive_get_elt_at_index \
-                       _bfd_archive_coff_get_elt_at_index
-#define bfd_elf64_archive_generic_stat_arch_elt \
-                       _bfd_archive_coff_generic_stat_arch_elt
-#define bfd_elf64_archive_update_armap_timestamp \
-                       _bfd_archive_coff_update_armap_timestamp
-
 /* The SGI style (n)64 NewABI.  */
 #define TARGET_LITTLE_SYM              mips_elf64_le_vec
 #define TARGET_LITTLE_NAME             "elf64-littlemips"
This page took 0.026383 seconds and 4 git commands to generate.