Delete relocations associatesd with deleted exidx entries.
authorAkihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>
Fri, 23 Sep 2016 15:32:04 +0000 (16:32 +0100)
committerNick Clifton <nickc@redhat.com>
Fri, 23 Sep 2016 15:32:04 +0000 (16:32 +0100)
PR ld/20595
ld * testsuite/ld-arm/unwind-4.d: Add -q option to linker command
line and -r option to objdump command line.  Match emitted relocs
to make sure that superflous relocs are not generated.

bfd * elf-bfd.h (struct elf_backend_data): Add
elf_backend_count_output_relocs callback to count relocations in
the final output.
* elf-arm.c (elf32_arm_add_relocation): Deleted.
(elf32_arm_write_section): Move additional relocation to emit_relocs.
(elf32_arm_count_output_relocs): New function.
(emit_relocs): New function.
(elf32_arm_emit_relocs): New function.
(elf32_arm_vxworks_emit_relocs): New function.
(elf_backend_emit_relocs): Updated to use the new functions.
(elf_backend_count_output_relocs): New define.
* bfd/elflink.c (bfd_elf_final_link): Do not add additional_reloc_count
to the relocation count.
(_bfd_elf_link_size_reloc_section): Use callback to count the
relocations which will be in output.
(_bfd_elf_default_count_output_relocs): New function.
* bfd/elfxx-target.h (elf_backend_count_output_relocs): New define.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-arm.c
bfd/elflink.c
bfd/elfxx-target.h
ld/ChangeLog
ld/testsuite/ld-arm/unwind-4.d

index 36624ee..4e1d209 100644 (file)
@@ -1,3 +1,24 @@
+2016-09-23  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+       PR ld/20595
+       * elf-bfd.h (struct elf_backend_data): Add
+       elf_backend_count_output_relocs callback to count relocations in
+       the final output.
+       * elf-arm.c (elf32_arm_add_relocation): Deleted.
+       (elf32_arm_write_section): Move additional relocation to emit_relocs.
+       (elf32_arm_count_output_relocs): New function.
+       (emit_relocs): New function.
+       (elf32_arm_emit_relocs): New function.
+       (elf32_arm_vxworks_emit_relocs): New function.
+       (elf_backend_emit_relocs): Updated to use the new functions.
+       (elf_backend_count_output_relocs): New define.
+       * bfd/elflink.c (bfd_elf_final_link): Do not add additional_reloc_count
+       to the relocation count.
+       (_bfd_elf_link_size_reloc_section): Use callback to count the
+       relocations which will be in output.
+       (_bfd_elf_default_count_output_relocs): New function.
+       * bfd/elfxx-target.h (elf_backend_count_output_relocs): New define.
+
 2016-09-19  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * elfxx-sparc.c (_bfd_sparc_elf_size_dynamic_sections): Allow
index d18df17..c58bd4f 100644 (file)
@@ -1183,6 +1183,11 @@ struct elf_backend_data
   unsigned int (*elf_backend_count_additional_relocs)
     (asection *);
 
+  /* Count relocations to be output.  The result may be different if the
+     input relocations are expected to be modified by the backend.  */
+  unsigned int (* elf_backend_count_output_relocs)
+    (struct bfd_link_info *, asection *, bfd_boolean is_rela);
+
   /* Say whether to sort relocs output by ld -r and ld --emit-relocs,
      by r_offset.  If NULL, default to true.  */
   bfd_boolean (*sort_relocs_p)
@@ -2152,6 +2157,9 @@ extern bfd_boolean _bfd_elf_link_output_relocs
   (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *,
    struct elf_link_hash_entry **);
 
+extern unsigned int _bfd_elf_default_count_output_relocs
+  (struct bfd_link_info * ATTRIBUTE_UNUSED, asection *, bfd_boolean);
+
 extern bfd_boolean _bfd_elf_adjust_dynamic_copy
   (struct bfd_link_info *, struct elf_link_hash_entry *, asection *);
 
index 6e68be1..c58b65d 100644 (file)
@@ -8592,8 +8592,8 @@ bfd_elf32_arm_stm32l4xx_erratum_scan (bfd *abfd,
                     if the instruction is not the last instruction of
                     an IT block, we cannot create a jump there, so we
                     bail out.  */
-                   if ((is_ldm || is_vldm) &&
-                       stm32l4xx_need_create_replacing_stub
+                   if ((is_ldm || is_vldm)
+                       && stm32l4xx_need_create_replacing_stub
                        (insn, globals->stm32l4xx_fix))
                      {
                        if (is_not_last_in_it_block)
@@ -8641,8 +8641,8 @@ bfd_elf32_arm_stm32l4xx_erratum_scan (bfd *abfd,
                     There can be no nested IT blocks so an IT block
                     is naturally a new one for which it is worth
                     computing its size.  */
-                 bfd_boolean is_newitblock = ((insn & 0xff00) == 0xbf00) &&
-                   ((insn & 0x000f) != 0x0000);
+                 bfd_boolean is_newitblock = ((insn & 0xff00) == 0xbf00)
+                   && ((insn & 0x000f) != 0x0000);
                  /* If we have a new IT block we compute its size.  */
                  if (is_newitblock)
                    {
@@ -11066,9 +11066,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                {
                  if (dynreloc_st_type == STT_GNU_IFUNC)
                    outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
-                 else if (bfd_link_pic (info) &&
-                          (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                           || h->root.type != bfd_link_hash_undefweak))
+                 else if (bfd_link_pic (info)
+                          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                              || h->root.type != bfd_link_hash_undefweak))
                    outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
                  else
                    outrel.r_info = 0;
@@ -11100,8 +11100,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        {
          bfd_vma off;
 
-         BFD_ASSERT (local_got_offsets != NULL &&
-                     local_got_offsets[r_symndx] != (bfd_vma) -1);
+         BFD_ASSERT (local_got_offsets != NULL
+                     && local_got_offsets[r_symndx] != (bfd_vma) -1);
 
          off = local_got_offsets[r_symndx];
 
@@ -14906,8 +14906,8 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
                  if (ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
                    {
                      cmse_sec = cmse_hash->root.root.u.def.section;
-                     if (!cmse_sec->gc_mark &&
-                         !_bfd_elf_gc_mark (info, cmse_sec, gc_mark_hook))
+                     if (!cmse_sec->gc_mark
+                         && !_bfd_elf_gc_mark (info, cmse_sec, gc_mark_hook))
                        return FALSE;
                    }
                }
@@ -15950,9 +15950,9 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
              || !add_dynamic_entry (DT_JMPREL, 0))
            return FALSE;
 
-         if (htab->dt_tlsdesc_plt &&
-               (!add_dynamic_entry (DT_TLSDESC_PLT,0)
-                || !add_dynamic_entry (DT_TLSDESC_GOT,0)))
+         if (htab->dt_tlsdesc_plt
+             && (!add_dynamic_entry (DT_TLSDESC_PLT,0)
+                 || !add_dynamic_entry (DT_TLSDESC_GOT,0)))
            return FALSE;
        }
 
@@ -18243,39 +18243,6 @@ stm32l4xx_create_replacing_stub (struct elf32_arm_link_hash_table * htab,
 /* End of stm32l4xx work-around.  */
 
 
-static void
-elf32_arm_add_relocation (bfd *output_bfd, struct bfd_link_info *info,
-                         asection *output_sec, Elf_Internal_Rela *rel)
-{
-  BFD_ASSERT (output_sec && rel);
-  struct bfd_elf_section_reloc_data *output_reldata;
-  struct elf32_arm_link_hash_table *htab;
-  struct bfd_elf_section_data *oesd = elf_section_data (output_sec);
-  Elf_Internal_Shdr *rel_hdr;
-
-
-  if (oesd->rel.hdr)
-    {
-      rel_hdr = oesd->rel.hdr;
-      output_reldata = &(oesd->rel);
-    }
-  else if (oesd->rela.hdr)
-    {
-      rel_hdr = oesd->rela.hdr;
-      output_reldata = &(oesd->rela);
-    }
-  else
-    {
-      abort ();
-    }
-
-  bfd_byte *erel = rel_hdr->contents;
-  erel += output_reldata->count * rel_hdr->sh_entsize;
-  htab = elf32_arm_hash_table (info);
-  SWAP_RELOC_OUT (htab) (output_bfd, rel, erel);
-  output_reldata->count++;
-}
-
 /* Do code byteswapping.  Return FALSE afterwards so that the section is
    written out as normal.  */
 
@@ -18527,18 +18494,6 @@ elf32_arm_write_section (bfd *output_bfd,
                               adjust offset by hand.  */
                            prel31_offset = text_sec->output_offset
                                            + text_sec->size;
-
-                           /* New relocation entity.  */
-                           asection *text_out = text_sec->output_section;
-                           Elf_Internal_Rela rel;
-                           rel.r_addend = 0;
-                           rel.r_offset = exidx_offset;
-                           rel.r_info = ELF32_R_INFO (text_out->target_index,
-                                                      R_ARM_PREL31);
-
-                           elf32_arm_add_relocation (output_bfd, link_info,
-                                                     sec->output_section,
-                                                     &rel);
                          }
 
                        /* First address we can't unwind.  */
@@ -19060,9 +19015,84 @@ elf32_arm_count_additional_relocs (asection *sec)
 {
   struct _arm_elf_section_data *arm_data;
   arm_data = get_arm_elf_section_data (sec);
+
   return arm_data == NULL ? 0 : arm_data->additional_reloc_count;
 }
 
+static unsigned int
+elf32_arm_count_output_relocs (struct bfd_link_info *  info,
+                              asection *              o,
+                              bfd_boolean             rela)
+{
+  struct bfd_elf_section_data *esdo;
+  struct bfd_link_order *p;
+  bfd_size_type count;
+
+  esdo = elf_section_data (o->output_section);
+  if (esdo->this_hdr.sh_type != SHT_ARM_EXIDX)
+    return _bfd_elf_default_count_output_relocs (info, o, rela);
+
+  /* PR 20595: Skip relocations for deleted exidx entries.  */
+  count = 0;
+  for (p = o->map_head.link_order; p != NULL; p = p->next)
+    {
+      struct _arm_elf_section_data *arm_data;
+      struct bfd_elf_section_data *esd;
+      arm_unwind_table_edit *edit_list;
+      Elf_Internal_Rela *relocs;
+      asection *sec;
+      bfd_size_type num_rel;
+      bfd_size_type num_rela;
+      unsigned int i;
+
+      if (p->type == bfd_section_reloc_link_order
+         || p->type == bfd_symbol_reloc_link_order)
+       {
+         count++;
+         continue;
+       }
+
+      sec = p->u.indirect.section;
+      arm_data = get_arm_elf_section_data (sec);
+      esd = &arm_data->elf;
+
+      if (arm_data->additional_reloc_count)
+       count += arm_data->additional_reloc_count;
+
+      edit_list = arm_data->u.exidx.unwind_edit_list;
+      if (!edit_list)
+       {
+         count += sec->reloc_count;
+         continue;
+       }
+
+      relocs = _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL,
+                                         info->keep_memory);
+      num_rel = esd->rel.hdr ? NUM_SHDR_ENTRIES (esd->rel.hdr) : 0;
+      num_rela = esd->rela.hdr ? NUM_SHDR_ENTRIES (esd->rela.hdr) : 0;
+      if (rela)
+       relocs += num_rel;
+
+      for (i = 0; i < (rela ? num_rela : num_rel); i++)
+       {
+         arm_unwind_table_edit *edit_node;
+         unsigned int index;
+
+         index = (relocs[i].r_offset - sec->vma) / 8;
+
+         for (edit_node = edit_list;
+              edit_node->next && edit_node->next->index > index;
+              edit_node++);
+
+         if (edit_node->type != DELETE_EXIDX_ENTRY
+             || edit_node->index != index)
+           count++;
+       }
+    }
+
+  return count;
+}
+
 /* Called to set the sh_flags, sh_link and sh_info fields of OSECTION which
    has a type >= SHT_LOOS.  Returns TRUE if these fields were initialised 
    FALSE otherwise.  ISECTION is the best guess matching section from the
@@ -19191,6 +19221,139 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
     sym->flags |= BSF_KEEP;
 }
 
+static bfd_boolean
+emit_relocs (bfd *                          output_bfd,
+            asection *                     input_section,
+            Elf_Internal_Shdr *            input_rel_hdr,
+            Elf_Internal_Rela *            internal_relocs,
+            struct elf_link_hash_entry **  rel_hash,
+            bfd_boolean (*                 fallback) (bfd *, asection *,
+                                                      Elf_Internal_Shdr *,
+                                                      Elf_Internal_Rela *,
+                                                      struct elf_link_hash_entry **))
+{
+  _arm_elf_section_data *arm_data;
+  struct bfd_elf_section_reloc_data *output_reldata;
+  Elf_Internal_Shdr *output_rel_hdr;
+  Elf_Internal_Rela *irela;
+  Elf_Internal_Rela *irelaend;
+  asection *output_section;
+  const struct elf_backend_data *bed;
+  void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
+  struct bfd_elf_section_data *esdo;
+  arm_unwind_table_edit *edit_list, *edit_tail;
+  bfd_byte *erel;
+  bfd_vma offset;
+
+  arm_data = get_arm_elf_section_data (input_section);
+
+  if (!arm_data || arm_data->elf.this_hdr.sh_type != SHT_ARM_EXIDX)
+    goto fallback_label;
+
+  edit_list = arm_data->u.exidx.unwind_edit_list;
+  edit_tail = arm_data->u.exidx.unwind_edit_tail;
+
+  if (!edit_list)
+    goto fallback_label;
+
+  output_section = input_section->output_section;
+  offset = output_section->vma + input_section->output_offset;
+
+  bed = get_elf_backend_data (output_bfd);
+  esdo = elf_section_data (output_section);
+  if (esdo->rel.hdr && esdo->rel.hdr->sh_entsize == input_rel_hdr->sh_entsize)
+    {
+      output_reldata = &esdo->rel;
+      swap_out = bed->s->swap_reloc_out;
+    }
+  else if (esdo->rela.hdr
+          && esdo->rela.hdr->sh_entsize == input_rel_hdr->sh_entsize)
+    {
+      output_reldata = &esdo->rela;
+      swap_out = bed->s->swap_reloca_out;
+    }
+  else
+    {
+      (*_bfd_error_handler)
+       (_("%B: relocation size mismatch in %B section %A"),
+        output_bfd, input_section->owner, input_section);
+        bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
+
+  output_rel_hdr = output_reldata->hdr;
+  erel = output_rel_hdr->contents;
+  erel += output_reldata->count * input_rel_hdr->sh_entsize;
+
+  irela = internal_relocs;
+  irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
+                     * bed->s->int_rels_per_ext_rel);
+  while (irela < irelaend)
+    {
+      arm_unwind_table_edit *edit_node, *edit_next;
+      Elf_Internal_Rela rel;
+      bfd_vma bias;
+      bfd_vma index;
+
+      index = (irela->r_offset - offset) / 8;
+
+      bias = 0;
+      edit_node = edit_list;
+      for (edit_next = edit_list;
+          edit_next && edit_next->index <= index;
+          edit_next = edit_node->next)
+       {
+         bias++;
+         edit_node = edit_next;
+       }
+
+      if (edit_node->type != DELETE_EXIDX_ENTRY || edit_node->index != index)
+       {
+         rel.r_offset = irela->r_offset - bias * 8;
+         rel.r_info = irela->r_info;
+         rel.r_addend = irela->r_addend;
+
+         (*swap_out) (output_bfd, &rel, erel);
+         erel += output_rel_hdr->sh_entsize;
+         output_reldata->count++;
+       }
+
+      irela += bed->s->int_rels_per_ext_rel;
+    }
+
+  if (edit_tail->type == INSERT_EXIDX_CANTUNWIND_AT_END)
+    {
+      /* New relocation entity.  */
+      asection *text_sec = edit_tail->linked_section;
+      asection *text_out = text_sec->output_section;
+      bfd_vma exidx_offset = offset + input_section->size - 8;
+      Elf_Internal_Rela rel;
+
+      rel.r_addend = 0;
+      rel.r_offset = exidx_offset;
+      rel.r_info = ELF32_R_INFO (text_out->target_index, R_ARM_PREL31);
+      (*swap_out) (output_bfd, &rel, erel);
+      output_reldata->count++;
+    }
+
+  return TRUE;
+
+fallback_label:
+  return fallback (output_bfd, input_section, input_rel_hdr,
+                  internal_relocs, rel_hash);
+}
+
+static bfd_boolean
+elf32_arm_emit_relocs (bfd *                          output_bfd,
+                      asection *                     input_section,
+                      Elf_Internal_Shdr *            input_rel_hdr,
+                      Elf_Internal_Rela *            internal_relocs,
+                      struct elf_link_hash_entry **  rel_hash)
+{
+  return emit_relocs (output_bfd, input_section, input_rel_hdr, internal_relocs,
+                     rel_hash, _bfd_elf_link_output_relocs);
+}
+
 #undef  elf_backend_copy_special_section_fields
 #define elf_backend_copy_special_section_fields elf32_arm_copy_special_section_fields
 
@@ -19221,6 +19384,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #define bfd_elf32_bfd_final_link               elf32_arm_final_link
 #define bfd_elf32_get_synthetic_symtab  elf32_arm_get_synthetic_symtab
 
+#define elf_backend_emit_relocs                        elf32_arm_emit_relocs
 #define elf_backend_get_symbol_type             elf32_arm_get_symbol_type
 #define elf_backend_gc_mark_hook                elf32_arm_gc_mark_hook
 #define elf_backend_gc_mark_extra_sections     elf32_arm_gc_mark_extra_sections
@@ -19250,6 +19414,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #define elf_backend_begin_write_processing      elf32_arm_begin_write_processing
 #define elf_backend_add_symbol_hook            elf32_arm_add_symbol_hook
 #define elf_backend_count_additional_relocs    elf32_arm_count_additional_relocs
+#define elf_backend_count_output_relocs                elf32_arm_count_output_relocs
 #define elf_backend_symbol_processing          elf32_arm_backend_symbol_processing
 
 #define elf_backend_can_refcount       1
@@ -19275,9 +19440,9 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #define elf_backend_obj_attrs_order            elf32_arm_obj_attrs_order
 #define elf_backend_obj_attrs_handle_unknown   elf32_arm_obj_attrs_handle_unknown
 
-#undef elf_backend_section_flags
+#undef  elf_backend_section_flags
 #define elf_backend_section_flags              elf32_arm_section_flags
-#undef elf_backend_lookup_section_flags_hook
+#undef  elf_backend_lookup_section_flags_hook
 #define elf_backend_lookup_section_flags_hook   elf32_arm_lookup_section_flags
 
 #include "elf32-target.h"
@@ -19416,6 +19581,17 @@ elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
   elf_vxworks_final_write_processing (abfd, linker);
 }
 
+static bfd_boolean
+elf32_arm_vxworks_emit_relocs (bfd *                          output_bfd,
+                              asection *                     input_section,
+                              Elf_Internal_Shdr *            input_rel_hdr,
+                              Elf_Internal_Rela *            internal_relocs,
+                              struct elf_link_hash_entry **  rel_hash)
+{
+  return emit_relocs (output_bfd, input_section, input_rel_hdr, internal_relocs,
+                     rel_hash, elf_vxworks_emit_relocs);
+}
+
 #undef  elf32_bed
 #define elf32_bed elf32_arm_vxworks_bed
 
@@ -19424,7 +19600,7 @@ elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 #undef  elf_backend_final_write_processing
 #define elf_backend_final_write_processing     elf32_arm_vxworks_final_write_processing
 #undef  elf_backend_emit_relocs
-#define elf_backend_emit_relocs                        elf_vxworks_emit_relocs
+#define elf_backend_emit_relocs                        elf32_arm_vxworks_emit_relocs
 
 #undef  elf_backend_may_use_rel_p
 #define elf_backend_may_use_rel_p      0
@@ -19787,7 +19963,8 @@ elf32_arm_symbian_plt_sym_val (bfd_vma i, const asection *plt,
 #define ELF_DYNAMIC_SEC_FLAGS \
   (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED)
 
-#undef elf_backend_emit_relocs
+#undef  elf_backend_emit_relocs
+#define elf_backend_emit_relocs                        elf32_arm_emit_relocs
 
 #undef  bfd_elf32_bfd_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_create   elf32_arm_symbian_link_hash_table_create
index 9e9a33c..e35ce02 100644 (file)
@@ -2449,13 +2449,23 @@ _bfd_elf_link_read_relocs (bfd *abfd,
    section header for a section containing relocations for O.  */
 
 static bfd_boolean
-_bfd_elf_link_size_reloc_section (bfd *abfd,
-                                 struct bfd_elf_section_reloc_data *reldata)
+_bfd_elf_link_size_reloc_section (bfd *abfd, struct bfd_link_info *info,
+                                 asection *o, bfd_boolean rela)
 {
-  Elf_Internal_Shdr *rel_hdr = reldata->hdr;
+  struct bfd_elf_section_data *esdo;
+  const struct elf_backend_data *bed;
+  struct bfd_elf_section_reloc_data *reldata;
+  Elf_Internal_Shdr *rel_hdr;
+  unsigned int count;
+
+  esdo = elf_section_data (o);
+  reldata = rela ? &esdo->rela : &esdo->rel;
+  rel_hdr = reldata->hdr;
 
   /* That allows us to calculate the size of the section.  */
-  rel_hdr->sh_size = rel_hdr->sh_entsize * reldata->count;
+  bed = get_elf_backend_data (abfd);
+  count = (*bed->elf_backend_count_output_relocs) (info, o, rela);
+  rel_hdr->sh_size = count * rel_hdr->sh_entsize;
 
   /* The contents field must last into write_object_contents, so we
      allocate it with bfd_alloc rather than malloc.  Also since we
@@ -2543,6 +2553,20 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
 
   return TRUE;
 }
+
+unsigned int
+_bfd_elf_default_count_output_relocs (struct bfd_link_info *  info ATTRIBUTE_UNUSED,
+                                     asection *              o,
+                                     bfd_boolean             rela)
+{
+  struct bfd_elf_section_data *esdo;
+  struct bfd_elf_section_reloc_data *reldata;
+
+  esdo = elf_section_data (o);
+  reldata = rela ? &esdo->rela : &esdo->rel;
+
+  return reldata->count;
+}
 \f
 /* Make weak undefined symbols in PIE dynamic.  */
 
@@ -11286,12 +11310,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       struct bfd_elf_section_data *esdo = elf_section_data (o);
+      unsigned int additional_reloc_count = 0;
       o->reloc_count = 0;
 
       for (p = o->map_head.link_order; p != NULL; p = p->next)
        {
          unsigned int reloc_count = 0;
-         unsigned int additional_reloc_count = 0;
          struct bfd_elf_section_data *esdi = NULL;
 
          if (p->type == bfd_section_reloc_link_order
@@ -11377,21 +11401,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          if (reloc_count == 0)
            continue;
 
-         reloc_count += additional_reloc_count;
          o->reloc_count += reloc_count;
 
          if (p->type == bfd_indirect_link_order && emit_relocs)
            {
              if (esdi->rel.hdr)
-               {
                  esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr);
-                 esdo->rel.count += additional_reloc_count;
-               }
              if (esdi->rela.hdr)
-               {
                  esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr);
-                 esdo->rela.count += additional_reloc_count;
-               }
            }
          else
            {
@@ -11402,7 +11419,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            }
        }
 
-      if (o->reloc_count > 0)
+      if (o->reloc_count > 0 || additional_reloc_count > 0)
        o->flags |= SEC_RELOC;
       else
        {
@@ -11440,11 +11457,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       if ((o->flags & SEC_RELOC) != 0)
        {
          if (esdo->rel.hdr
-             && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rel)))
+             && !(_bfd_elf_link_size_reloc_section (abfd, info, o, FALSE)))
            goto error_return;
 
          if (esdo->rela.hdr
-             && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rela)))
+             && !(_bfd_elf_link_size_reloc_section (abfd, info, o, TRUE)))
            goto error_return;
        }
 
index 364bddf..0f6f5c5 100644 (file)
 #ifndef elf_backend_count_additional_relocs
 #define elf_backend_count_additional_relocs    NULL
 #endif
+#ifndef elf_backend_count_output_relocs
+#define elf_backend_count_output_relocs                _bfd_elf_default_count_output_relocs
+#endif
 #ifndef elf_backend_sort_relocs_p
 #define elf_backend_sort_relocs_p              NULL
 #endif
@@ -777,6 +780,7 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_emit_relocs,
   elf_backend_count_relocs,
   elf_backend_count_additional_relocs,
+  elf_backend_count_output_relocs,
   elf_backend_sort_relocs_p,
   elf_backend_grok_prstatus,
   elf_backend_grok_psinfo,
index ee43d40..56e6133 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-23  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+       PR ld/20595
+       * testsuite/ld-arm/unwind-4.d: Add -q option to linker command
+       line and -r option to objdump command line.  Match emitted relocs
+       to make sure that superflous relocs are not generated.
+
 2016-09-23  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * emulparams/elf64_s390.sh: Change TEXT_START_ADDR to 256MB.
index 0a4427a..0bed0dc 100644 (file)
@@ -1,9 +1,23 @@
-#ld: -T arm.ld
-#objdump: -s
+#ld: -q -T arm.ld
+#objdump: -sr
 
 .*:     file format.*
 
 #...
+RELOCATION RECORDS FOR \[\.ARM\.exidx\]:
+OFFSET   TYPE              VALUE 
+00000000 R_ARM_PREL31      \.text
+00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
+00000008 R_ARM_PREL31      \.text
+00000008 R_ARM_NONE        __aeabi_unwind_cpp_pr1
+0000000c R_ARM_PREL31      \.text
+00000010 R_ARM_PREL31      \.text
+00000010 R_ARM_NONE        __aeabi_unwind_cpp_pr0
+00000018 R_ARM_PREL31      \.text
+
+
+Contents of section .text:
+#...
 Contents of section .ARM.exidx:
  8020 (e0ffff7f b0b0a880 dcffff7f e8ffff7f|7fffffe0 80a8b0b0 7fffffdc 7fffffe8)  .*
  8030 (d8ffff7f b0b0a880 d8ffff7f 01000000|7fffffd8 80a8b0b0 7fffffd8 00000001)  .*