[PATCH] ARM: Update the hash table for relocations associated with exidx entries

Akihiko Odaki akihiko.odaki.4i@stu.hosei.ac.jp
Wed Sep 28 04:03:00 GMT 2016


This reverts some changes in commit
5025eb7c0d87b01507116353b5d63b163d7add3d.

     PR ld/20636
bfd  * elf-bfd.h (struct elf_backend_data): Delete
     elf_backend_count_output_relocs callback and add
     elf_backend_update_relocs.
     * elf32-arm.c (elf32_arm_count_output_relocs): Deleted.
     (emit_relocs): Deleted.
     (elf32_arm_emit_relocs): Deleted.
     (elf_backend_emit_relocs): Updated not to use the old functions.
     (elf32_arm_update_relocs): New function.
     (elf_backend_update_relocs): New define.
     * elflink.c (bfd_elf_final_link): Add additional_reloc_count to the
     relocation count. Call elf_backend_emit_relocs.
     (_bfd_elf_size_reloc_section): Do not call
     elf_backend_count_output_relocs.
     * elfxx-target.h (elf_backend_count_output_relocs): Deleted.
     (elf_backend_update_relocs): New define.
---
 bfd/ChangeLog      |  19 +++
 bfd/elf-bfd.h      |  15 +--
 bfd/elf32-arm.c    | 387 +++++++++++++++++++++++------------------------------
 bfd/elflink.c      |  55 +++-----
 bfd/elfxx-target.h |   8 +-
 5 files changed, 215 insertions(+), 269 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4e1d209..82f7209 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,22 @@
+2016-09-28  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	PR ld/20636
+	* elf-bfd.h (struct elf_backend_data): Delete
+	elf_backend_count_output_relocs callback and add
+	elf_backend_update_relocs.
+	* elf32-arm.c (elf32_arm_count_output_relocs): Deleted.
+	(emit_relocs): Deleted.
+	(elf32_arm_emit_relocs): Deleted.
+	(elf_backend_emit_relocs): Updated not to use the old functions.
+	(elf32_arm_update_relocs): New function.
+	(elf_backend_update_relocs): New define.
+	* elflink.c (bfd_elf_final_link): Add additional_reloc_count to the
+	relocation count. Call elf_backend_emit_relocs.
+	(_bfd_elf_size_reloc_section): Do not call
+	elf_backend_count_output_relocs.
+	* elfxx-target.h (elf_backend_count_output_relocs): Deleted.
+	(elf_backend_update_relocs): New define.
+
 2016-09-23  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
 
 	PR ld/20595
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index c58bd4f..c0d3a69 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -756,6 +756,8 @@ typedef asection * (*elf_gc_mark_hook_fn)
   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
    struct elf_link_hash_entry *, Elf_Internal_Sym *);
 
+struct bfd_elf_section_reloc_data;
+
 struct elf_backend_data
 {
   /* The architecture for this backend.  */
@@ -1173,6 +1175,11 @@ struct elf_backend_data
     (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *,
      struct elf_link_hash_entry **);
 
+  /* Update relocations.  It is allowed to change the number and the order.
+     In such a case hashes should be invalidated. */
+  void (*elf_backend_update_relocs)
+    (asection *, struct bfd_elf_section_reloc_data *reldata);
+
   /* Count relocations.  Not called for relocatable links
      or if all relocs are being preserved in the output.  */
   unsigned int (*elf_backend_count_relocs)
@@ -1183,11 +1190,6 @@ 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)
@@ -2157,9 +2159,6 @@ 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 *);
 
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index c58b65d..72bb300 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -14827,6 +14827,167 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
   return TRUE;
 }
 
+static void
+elf32_arm_update_relocs (asection *o,
+			 struct bfd_elf_section_reloc_data *reldata)
+{
+  void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
+  void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
+  const struct elf_backend_data *bed;
+  _arm_elf_section_data *eado;
+  struct bfd_link_order *p;
+  bfd_byte *erela_head, *erela;
+  Elf_Internal_Rela *irela_head, *irela;
+  Elf_Internal_Shdr *rel_hdr;
+  bfd *abfd;
+  unsigned int count;
+
+  eado = get_arm_elf_section_data (o);
+
+  if (!eado || eado->elf.this_hdr.sh_type != SHT_ARM_EXIDX)
+    return;
+
+  abfd = o->owner;
+  bed = get_elf_backend_data (abfd);
+  rel_hdr = reldata->hdr;
+
+  if (rel_hdr->sh_entsize == bed->s->sizeof_rel)
+    {
+      swap_in = bed->s->swap_reloc_in;
+      swap_out = bed->s->swap_reloc_out;
+    }
+  else if (rel_hdr->sh_entsize == bed->s->sizeof_rela)
+    {
+      swap_in = bed->s->swap_reloca_in;
+      swap_out = bed->s->swap_reloca_out;
+    }
+  else
+    abort ();
+
+  erela_head = rel_hdr->contents;
+  irela_head = (Elf_Internal_Rela *) bfd_zmalloc (
+		 (NUM_SHDR_ENTRIES (rel_hdr) + 1) * sizeof (*irela_head));
+
+  erela = erela_head;
+  irela = irela_head;
+  count = 0;
+
+  for (p = o->map_head.link_order; p; p = p->next)
+    {
+      if (p->type == bfd_section_reloc_link_order
+	  || p->type == bfd_symbol_reloc_link_order)
+	{
+	  (*swap_in) (abfd, erela, irela);
+	  erela += rel_hdr->sh_entsize;
+	  irela++;
+	  count++;
+	}
+      else if (p->type == bfd_indirect_link_order)
+	{
+	  struct bfd_elf_section_reloc_data *input_reldata;
+	  arm_unwind_table_edit *edit_list, *edit_tail;
+	  _arm_elf_section_data *eadi;
+	  bfd_size_type j;
+	  bfd_vma offset;
+	  asection *i;
+
+	  i = p->u.indirect.section;
+
+	  eadi = get_arm_elf_section_data (i);
+	  edit_list = eadi->u.exidx.unwind_edit_list;
+	  edit_tail = eadi->u.exidx.unwind_edit_tail;
+	  offset = o->vma + i->output_offset;
+
+	  if (eadi->elf.rel.hdr &&
+	      eadi->elf.rel.hdr->sh_entsize == rel_hdr->sh_entsize)
+	    input_reldata = &eadi->elf.rel;
+	  else if (eadi->elf.rela.hdr &&
+		   eadi->elf.rela.hdr->sh_entsize == rel_hdr->sh_entsize)
+	    input_reldata = &eadi->elf.rela;
+	  else
+	    abort ();
+
+	  if (edit_list)
+	    {
+	      for (j = 0; j < NUM_SHDR_ENTRIES (input_reldata->hdr); j++)
+		{
+		  arm_unwind_table_edit *edit_node, *edit_next;
+		  bfd_vma bias;
+		  bfd_vma index;
+
+		  (*swap_in) (abfd, erela, irela);
+		  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)
+		    {
+		      irela->r_offset -= bias * 8;
+		      irela++;
+		      count++;
+		    }
+
+		  erela += rel_hdr->sh_entsize;
+		}
+
+	      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 + i->size - 8;
+
+		  irela->r_addend = 0;
+		  irela->r_offset = exidx_offset;
+		  irela->r_info = ELF32_R_INFO (
+				    text_out->target_index, R_ARM_PREL31);
+		  irela++;
+		  count++;
+		}
+	    }
+	  else
+	    {
+	      for (j = 0; j < NUM_SHDR_ENTRIES (input_reldata->hdr); j++)
+		{
+		  (*swap_in) (abfd, erela, irela);
+		  erela += rel_hdr->sh_entsize;
+		  irela++;
+		}
+
+	      count += NUM_SHDR_ENTRIES (input_reldata->hdr);
+	    }
+	}
+    }
+
+  reldata->count = count;
+  rel_hdr->sh_size = count * rel_hdr->sh_entsize;
+
+  erela = erela_head;
+  irela = irela_head;
+  while (count > 0)
+    {
+      (*swap_out) (abfd, irela, erela);
+      erela += rel_hdr->sh_entsize;
+      irela++;
+      count--;
+    }
+
+  free (irela_head);
+
+  /* Hashes are no longer valid.  */
+  free (reldata->hashes);
+  reldata->hashes = NULL;
+}
+
 /* Unwinding tables are not referenced directly.  This pass marks them as
    required if the corresponding code section is marked.  Similarly, ARMv8-M
    secure entry functions can only be referenced by SG veneers which are
@@ -19019,80 +19180,6 @@ elf32_arm_count_additional_relocs (asection *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
@@ -19221,139 +19308,6 @@ 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
 
@@ -19384,12 +19338,12 @@ elf32_arm_emit_relocs (bfd *                          output_bfd,
 #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
 #define elf_backend_gc_sweep_hook               elf32_arm_gc_sweep_hook
 #define elf_backend_check_relocs                elf32_arm_check_relocs
+#define elf_backend_update_relocs		elf32_arm_update_relocs
 #define elf_backend_relocate_section		elf32_arm_relocate_section
 #define elf_backend_write_section		elf32_arm_write_section
 #define elf_backend_adjust_dynamic_symbol	elf32_arm_adjust_dynamic_symbol
@@ -19414,7 +19368,6 @@ elf32_arm_emit_relocs (bfd *                          output_bfd,
 #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
@@ -19581,17 +19534,6 @@ 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
 
@@ -19600,7 +19542,7 @@ elf32_arm_vxworks_emit_relocs (bfd *                          output_bfd,
 #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			elf32_arm_vxworks_emit_relocs
+#define elf_backend_emit_relocs			elf_vxworks_emit_relocs
 
 #undef  elf_backend_may_use_rel_p
 #define elf_backend_may_use_rel_p	0
@@ -19963,8 +19905,7 @@ 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
-#define elf_backend_emit_relocs			elf32_arm_emit_relocs
+#undef elf_backend_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
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e35ce02..fbf8c00 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -2449,23 +2449,13 @@ _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_link_info *info,
-				  asection *o, bfd_boolean rela)
+_bfd_elf_link_size_reloc_section (bfd *abfd,
+				  struct bfd_elf_section_reloc_data *reldata)
 {
-  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;
+  Elf_Internal_Shdr *rel_hdr = reldata->hdr;
 
   /* That allows us to calculate the size of the section.  */
-  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;
+  rel_hdr->sh_size = rel_hdr->sh_entsize * reldata->count;
 
   /* The contents field must last into write_object_contents, so we
      allocate it with bfd_alloc rather than malloc.  Also since we
@@ -2553,20 +2543,6 @@ _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;
-}
 
 /* Make weak undefined symbols in PIE dynamic.  */
 
@@ -8354,6 +8330,7 @@ ext64b_r_offset (const void *p)
 
 static bfd_boolean
 elf_link_adjust_relocs (bfd *abfd,
+			asection *sec,
 			struct bfd_elf_section_reloc_data *reldata,
 			bfd_boolean sort)
 {
@@ -8412,6 +8389,9 @@ elf_link_adjust_relocs (bfd *abfd,
       (*swap_out) (abfd, irela, erela);
     }
 
+  if (bed->elf_backend_update_relocs)
+    (*bed->elf_backend_update_relocs) (sec, reldata);
+
   if (sort && count != 0)
     {
       bfd_vma (*ext_r_off) (const void *);
@@ -11310,12 +11290,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
@@ -11401,14 +11381,21 @@ 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
 	    {
@@ -11419,7 +11406,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	    }
 	}
 
-      if (o->reloc_count > 0 || additional_reloc_count > 0)
+      if (o->reloc_count > 0)
 	o->flags |= SEC_RELOC;
       else
 	{
@@ -11457,11 +11444,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, info, o, FALSE)))
+	      && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rel)))
 	    goto error_return;
 
 	  if (esdo->rela.hdr
-	      && !(_bfd_elf_link_size_reloc_section (abfd, info, o, TRUE)))
+	      && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rela)))
 	    goto error_return;
 	}
 
@@ -11963,10 +11950,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
       sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
       if (esdo->rel.hdr != NULL
-	  && !elf_link_adjust_relocs (abfd, &esdo->rel, sort))
+	  && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort))
 	return FALSE;
       if (esdo->rela.hdr != NULL
-	  && !elf_link_adjust_relocs (abfd, &esdo->rela, sort))
+	  && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort))
 	return FALSE;
 
       /* Set the reloc_count field to 0 to prevent write_relocs from
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 0f6f5c5..ba13012 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -548,15 +548,15 @@
 #ifndef elf_backend_emit_relocs
 #define elf_backend_emit_relocs			_bfd_elf_link_output_relocs
 #endif
+#ifndef elf_backend_update_relocs
+#define elf_backend_update_relocs		NULL
+#endif
 #ifndef elf_backend_count_relocs
 #define elf_backend_count_relocs		NULL
 #endif
 #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
@@ -778,9 +778,9 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_get_target_dtag,
   elf_backend_ignore_undef_symbol,
   elf_backend_emit_relocs,
+  elf_backend_update_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,
-- 
2.10.0



More information about the Binutils mailing list