@@ -2331,6 +2331,8 @@ extern const struct bfd_elf_special_section *_bfd_elf_get_special_section
(const char *, const struct bfd_elf_special_section *, unsigned int);
extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr
(bfd *, asection *);
+extern bool _bfd_elf_process_reverse_copy (asection *, unsigned int,
+ unsigned int);
extern bool _bfd_elf_link_hide_sym_by_version
(struct bfd_link_info *, struct elf_link_hash_entry *);
@@ -10851,6 +10851,41 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
return kept;
}
+/* Set SEC_ELF_REVERSE_COPY on section S when we need to reverse-copy
+ input .ctors/.dtors sections if they are placed in .init_array or
+ .finit_array for output. ADDRESS_SIZE is address in bytes.
+ INT_RELS_PER_EXT_REL is the number of internal relocations to
+ allocate per external relocation entry. */
+
+bool
+_bfd_elf_process_reverse_copy (asection *s, unsigned int address_size,
+ unsigned int int_rels_per_ext_rel)
+{
+ if (s->size <= address_size
+ || (s->flags & SEC_ELF_REVERSE_COPY) != 0)
+ return true;
+
+ if (((startswith (s->name, ".ctors")
+ && strcmp (s->output_section->name, ".init_array") == 0)
+ || (startswith (s->name, ".dtors")
+ && strcmp (s->output_section->name, ".fini_array") == 0))
+ && (s->name[6] == 0 || s->name[6] == '.'))
+ {
+ if (s->size * int_rels_per_ext_rel
+ != s->reloc_count * address_size)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("error: %pB: size of section %pA is not multiple of "
+ "address size"), s->owner, s);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ s->flags |= SEC_ELF_REVERSE_COPY;
+ }
+ return true;
+}
+
/* Link an input file into the linker output file. This function
handles all the sections and relocations of the input file at once.
This is so that we only have to read the local symbols once, and
@@ -11249,28 +11284,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
/* We need to reverse-copy input .ctors/.dtors sections if
they are placed in .init_array/.finit_array for output. */
- if (o->size > address_size
- && ((startswith (o->name, ".ctors")
- && strcmp (o->output_section->name,
- ".init_array") == 0)
- || (startswith (o->name, ".dtors")
- && strcmp (o->output_section->name,
- ".fini_array") == 0))
- && (o->name[6] == 0 || o->name[6] == '.'))
- {
- if (o->size * bed->s->int_rels_per_ext_rel
- != o->reloc_count * address_size)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("error: %pB: size of section %pA is not "
- "multiple of address size"),
- input_bfd, o);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- o->flags |= SEC_ELF_REVERSE_COPY;
- }
+ if (!_bfd_elf_process_reverse_copy (o, address_size,
+ bed->s->int_rels_per_ext_rel))
+ return false;
action_discarded = -1;
if (!elf_section_ignore_discarded_relocs (o))