ELF/BFD: Hold the number of internal static relocs in `->reloc_count'
authorMaciej W. Rozycki <macro@imgtec.com>
Tue, 6 Jun 2017 00:24:06 +0000 (01:24 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Tue, 6 Jun 2017 00:34:23 +0000 (01:34 +0100)
Correct a commit e5713223cbc1 ("MIPS/BFD: For n64 hold the number of
internal relocs in `->reloc_count'") regression and change internal
relocation handling in the generic ELF BFD linker code such that, except
in the presence of R_SPARC_OLO10 relocations, a section's `reloc_count'
holds the number of internal rather than external relocations, making
the handling more consistent between GAS, which sets `->reloc_count'
with a call to `bfd_set_reloc', and LD, which sets `->reloc_count' as it
reads input sections.

The handling of dynamic relocations remains unchanged and they continue
holding the number of external relocations in `->reloc_count'; they are
also not converted to the internal form except in `elf_link_sort_relocs'
(which does not handle the general, i.e. non-n64-MIPS case of composed
relocations correctly as per the ELF gABI, though it does not seem to
matter for the targets we currently support).

The n64 MIPS backend is the only one with `int_rels_per_ext_rel' set to
non-one, and consequently the change is trivial for all the remaining
backends and targets.

bfd/
* elf-bfd.h (RELOC_AGAINST_DISCARDED_SECTION): Subtract `count'
from `reloc_count' rather than decrementing it.
* elf.c (bfd_section_from_shdr): Multiply the adjustment to
`reloc_count' by `int_rels_per_ext_rel'.
* elf32-score.c (score_elf_final_link_relocate): Do not multiply
`reloc_count' by `int_rels_per_ext_rel' for last relocation
entry determination.
(s3_bfd_score_elf_check_relocs): Likewise.
* elf32-score7.c (score_elf_final_link_relocate): Likewise.
(s7_bfd_score_elf_relocate_section): Likewise.
(s7_bfd_score_elf_check_relocs): Likewise.
* elf64-mips.c (mips_elf64_get_reloc_upper_bound): Remove
prototype and function.
(mips_elf64_slurp_one_reloc_table): Do not update `reloc_count'.
(mips_elf64_slurp_reloc_table): Assert that `reloc_count' is
triple rather than once the sum of REL and RELA relocation entry
counts.
(bfd_elf64_get_reloc_upper_bound): Remove macro.
* elflink.c (_bfd_elf_link_read_relocs): Do not multiply
`reloc_count' by `int_rels_per_ext_rel' for internal relocation
storage allocation size determination.
(elf_link_input_bfd): Multiply `.ctors' and `.dtors' section's
size by `int_rels_per_ext_rel'.  Do not multiply `reloc_count'
by `int_rels_per_ext_rel' for last relocation entry
determination.
(bfd_elf_final_link): Do not multiply `reloc_count' by
`int_rels_per_ext_rel' for internal relocation storage
allocation size determination.
(init_reloc_cookie_rels): Do not multiply `reloc_count' by
`int_rels_per_ext_rel' for last relocation entry determination.
(elf_gc_smash_unused_vtentry_relocs): Likewise.
* elfxx-mips.c (_bfd_mips_elf_check_relocs): Likewise.
(_bfd_mips_elf_relocate_section): Likewise.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-score.c
bfd/elf32-score7.c
bfd/elf64-mips.c
bfd/elflink.c
bfd/elfxx-mips.c

index f4a6afa8d390f5aacd1204ab855923d2fb611f8c..a13853503f65d006bd84be9d5df1620c7e5573bf 100644 (file)
@@ -1,3 +1,39 @@
+2017-06-06  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * elf-bfd.h (RELOC_AGAINST_DISCARDED_SECTION): Subtract `count'
+       from `reloc_count' rather than decrementing it.
+       * elf.c (bfd_section_from_shdr): Multiply the adjustment to
+       `reloc_count' by `int_rels_per_ext_rel'.
+       * elf32-score.c (score_elf_final_link_relocate): Do not multiply
+       `reloc_count' by `int_rels_per_ext_rel' for last relocation
+       entry determination.
+       (s3_bfd_score_elf_check_relocs): Likewise.
+       * elf32-score7.c (score_elf_final_link_relocate): Likewise.
+       (s7_bfd_score_elf_relocate_section): Likewise.
+       (s7_bfd_score_elf_check_relocs): Likewise.
+       * elf64-mips.c (mips_elf64_get_reloc_upper_bound): Remove
+       prototype and function.
+       (mips_elf64_slurp_one_reloc_table): Do not update `reloc_count'.
+       (mips_elf64_slurp_reloc_table): Assert that `reloc_count' is
+       triple rather than once the sum of REL and RELA relocation entry
+       counts.
+       (bfd_elf64_get_reloc_upper_bound): Remove macro.
+       * elflink.c (_bfd_elf_link_read_relocs): Do not multiply
+       `reloc_count' by `int_rels_per_ext_rel' for internal relocation
+       storage allocation size determination.
+       (elf_link_input_bfd): Multiply `.ctors' and `.dtors' section's
+       size by `int_rels_per_ext_rel'.  Do not multiply `reloc_count'
+       by `int_rels_per_ext_rel' for last relocation entry
+       determination.
+       (bfd_elf_final_link): Do not multiply `reloc_count' by
+       `int_rels_per_ext_rel' for internal relocation storage
+       allocation size determination.
+       (init_reloc_cookie_rels): Do not multiply `reloc_count' by
+       `int_rels_per_ext_rel' for last relocation entry determination.
+       (elf_gc_smash_unused_vtentry_relocs): Likewise.
+       * elfxx-mips.c (_bfd_mips_elf_check_relocs): Likewise.
+       (_bfd_mips_elf_relocate_section): Likewise.
+
 2017-06-05  Alan Modra  <amodra@gmail.com>
 
        PR 21529
index 4110ace3292935855979c3dd60337953585b4d73..820bc982af36e7afef5c63258cab3512c5766ee9 100644 (file)
@@ -2767,7 +2767,7 @@ extern asection _bfd_elf_large_com_section;
            memmove (rel, rel + count,                                  \
                     (relend - rel - count) * sizeof (*rel));           \
                                                                        \
-           input_section->reloc_count--;                               \
+           input_section->reloc_count -= count;                        \
            relend -= count;                                            \
            rel--;                                                      \
            continue;                                                   \
index 34d39c547b6c9b721554d7e488891ee5f41de633..b0da500dc7aa4846da6f3482a3344687ff3431b7 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2374,7 +2374,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        *hdr2 = *hdr;
        *p_hdr = hdr2;
        elf_elfsections (abfd)[shindex] = hdr2;
-       target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
+       target_sect->reloc_count += (NUM_SHDR_ENTRIES (hdr)
+                                    * bed->s->int_rels_per_ext_rel);
        target_sect->flags |= SEC_RELOC;
        target_sect->relocation = NULL;
        target_sect->rel_filepos = hdr->sh_offset;
index 44682766a9aac0ad9454f8956d72c4bf45f60d09..a8914e672eefc3883fac8f16aa338ddca225f6fc 100644 (file)
@@ -2038,7 +2038,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
       bfd_vma lo_value = 0;
 
       bed = get_elf_backend_data (output_bfd);
-      relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+      relend = relocs + input_section->reloc_count;
       lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
       if ((local_p) && (lo16_rel != NULL))
         {
@@ -2808,7 +2808,7 @@ s3_bfd_score_elf_check_relocs (bfd *abfd,
 
   sreloc = NULL;
   bed = get_elf_backend_data (abfd);
-  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; ++rel)
     {
       unsigned long r_symndx;
index abf9b32084e48139d8f6a774302ad7c90c03bf29..5075fa41e8cff49b424e9926d47a7a479578c538 100644 (file)
@@ -1906,7 +1906,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
       bfd_vma lo_value = 0;
 
       bed = get_elf_backend_data (output_bfd);
-      relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+      relend = relocs + input_section->reloc_count;
       lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
       if ((local_p) && (lo16_rel != NULL))
         {
@@ -1944,7 +1944,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
             addend |= 0xffffc000;
 
           bed = get_elf_backend_data (output_bfd);
-          relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+          relend = relocs + input_section->reloc_count;
           lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
           if ((local_p) && (lo16_rel != NULL))
             {
@@ -2481,7 +2481,7 @@ s7_bfd_score_elf_relocate_section (bfd *output_bfd,
                     addend |= 0xffffc000;
 
                   bed = get_elf_backend_data (output_bfd);
-                  relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+                  relend = relocs + input_section->reloc_count;
                   lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
                   if (lo16_rel != NULL)
                     {
@@ -2617,7 +2617,7 @@ s7_bfd_score_elf_check_relocs (bfd *abfd,
 
   sreloc = NULL;
   bed = get_elf_backend_data (abfd);
-  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; ++rel)
     {
       unsigned long r_symndx;
index e95db2c74d891b5697f0b7377353c57db8b78194..84f2a3f8fcd7016f57a91d5c7571725bfaba1b25 100644 (file)
@@ -86,8 +86,6 @@ 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_get_dynamic_reloc_upper_bound
   (bfd *);
 static bfd_boolean mips_elf64_slurp_one_reloc_table
@@ -3647,12 +3645,6 @@ 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)
 {
@@ -3819,8 +3811,6 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
        }
     }
 
-  asect->reloc_count += relent - relents;
-
   if (allocated != NULL)
     free (allocated);
 
@@ -3835,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,
@@ -3864,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));
 
@@ -3890,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,
@@ -4437,7 +4423,6 @@ 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_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
 #define bfd_elf64_mkobject             _bfd_mips_elf_mkobject
 
index 71da4c9fd03eb47c7096812e5e58ec3b50a08921..07d3ea5d9c51d481ba57ca4d8ba0db9872f8c419 100644 (file)
@@ -2450,8 +2450,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
     {
       bfd_size_type size;
 
-      size = o->reloc_count;
-      size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
+      size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela);
       if (keep_memory)
        internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
       else
@@ -10402,7 +10401,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                 ".fini_array") == 0))
              && (o->name[6] == 0 || o->name[6] == '.'))
            {
-             if (o->size != o->reloc_count * address_size)
+             if (o->size * bed->s->int_rels_per_ext_rel
+                 != o->reloc_count * address_size)
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
@@ -10426,7 +10426,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
             relocs against removed link-once sections.  */
 
          rel = internal_relocs;
-         relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+         relend = rel + o->reloc_count;
          for ( ; rel < relend; rel++)
            {
              unsigned long r_symndx = rel->r_info >> r_sym_shift;
@@ -10615,7 +10615,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              /* Adjust the reloc addresses and symbol indices.  */
 
              irela = internal_relocs;
-             irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+             irelaend = irela + o->reloc_count;
              rel_hash = esdo->rel.hashes + esdo->rel.count;
              /* We start processing the REL relocs, if any.  When we reach
                 IRELAMID in the loop, we switch to the RELA relocs.  */
@@ -11789,8 +11789,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (max_internal_reloc_count != 0)
     {
-      amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
-      amt *= sizeof (Elf_Internal_Rela);
+      amt = max_internal_reloc_count * sizeof (Elf_Internal_Rela);
       flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
       if (flinfo.internal_relocs == NULL)
        goto error_return;
@@ -12589,8 +12588,7 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
       if (cookie->rels == NULL)
        return FALSE;
       cookie->rel = cookie->rels;
-      cookie->relend = (cookie->rels
-                       + sec->reloc_count * bed->s->int_rels_per_ext_rel);
+      cookie->relend = cookie->rels + sec->reloc_count;
     }
   cookie->rel = cookie->rels;
   return TRUE;
@@ -13203,7 +13201,7 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
   bed = get_elf_backend_data (sec->owner);
   log_file_align = bed->s->log_file_align;
 
-  relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  relend = relstart + sec->reloc_count;
 
   for (rel = relstart; rel < relend; ++rel)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
index cbf39c0630a31c4f383ee268e48b1b357cf024d5..1ef27f677f156c04fb950735565298a55454f84b 100644 (file)
@@ -8102,7 +8102,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
 
   bed = get_elf_backend_data (abfd);
-  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  rel_end = relocs + sec->reloc_count;
 
   /* Check for the mips16 stub sections.  */
 
@@ -10034,7 +10034,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   const struct elf_backend_data *bed;
 
   bed = get_elf_backend_data (output_bfd);
-  relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+  relend = relocs + input_section->reloc_count;
   for (rel = relocs; rel < relend; ++rel)
     {
       const char *name;