This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ARM: Update the hash table for relocations associated with exidx entries
- From: Akihiko Odaki <akihiko dot odaki dot 4i at stu dot hosei dot ac dot jp>
- To: binutils at sourceware dot org
- Cc: Szabolcs Nagy <szabolcs dot nagy at arm dot com>, nd at arm dot com, Nick Clifton <nickc at redhat dot com>, Andreas Schwab <schwab at suse dot de>, Paul Brook <paul at codesourcery dot com>, Yury Usishchev <y dot usishchev at samsung dot com>, Akihiko Odaki <akihiko dot odaki dot 4i at stu dot hosei dot ac dot jp>
- Date: Wed, 28 Sep 2016 13:02:20 +0900
- Subject: [PATCH] ARM: Update the hash table for relocations associated with exidx entries
- Authentication-results: sourceware.org; auth=none
- Authentication-results: mailgw02.hosei.ac.jp; sender-id=none header.from=akihiko dot odaki dot 4i at stu dot hosei dot ac dot jp; spf=none smtp.mfrom=akihiko dot odaki dot 4i at stu dot hosei dot ac dot jp
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