[PATCH v3 2/9] elf: Extract _bfd_elf_process_reverse_copy

Alan Modra amodra@gmail.com
Wed Jan 12 02:28:00 GMT 2022


On Tue, Jan 11, 2022 at 06:06:27AM -0800, H.J. Lu via Binutils wrote:
> Extract _bfd_elf_process_reverse_copy from elf_link_input_bfd so that
> it can be called in check_relocs to set SEC_ELF_REVERSE_COPY before
> elf_link_input_bfd is called.
> 
> 	* elf-bfd.h (_bfd_elf_process_reverse_copy): New prototype.
> 	* elflink.c (_bfd_elf_process_reverse_copy): New.  Extracted
> 	from elf_link_input_bfd.
> 	(elf_link_input_bfd): Call _bfd_elf_process_reverse_copy.

You are correct that the flag needs to be set earlier so that
_bfd_elf_section_offset gives correct results when used earlier in the
linking process.  However, this is something that should be done once
for all ELF targets rather than in multiple places depending on
target, via a hook.

It must be done during or after map_input_to_output_sections, and
since your DT_RELR patchset makes decisions about relative relocations
in ldemul_before_allocation, during or before that.  But there isn't a
convenient iteration over all sections in ldelf_before_allocation.  So
I'm inclined to set the flag during map_input_to_output_sections, even
though it adds ELF specific code there.

I'll commit the following after running tests over my normal list of
targets.

bfd/
	* elflink.c (elf_link_input_bfd): Don't set SEC_ELF_REVERSE_COPY
	here.  Move sanity checks to reverse copying code.
ld/
	* ldlang.c (lang_add_section): Set SEC_ELF_REVERSE_COPY for
	.ctors/.dtors in .init_array/.fini_array.

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 059461b5725..f5e3fd53c5d 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11247,31 +11247,6 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 	      && o->reloc_count > 0)
 	    return false;
 
-	  /* 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;
-	    }
-
 	  action_discarded = -1;
 	  if (!elf_section_ignore_discarded_relocs (o))
 	    action_discarded = (*bed->action_discarded) (o);
@@ -11756,9 +11731,24 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
 		offset *= bfd_octets_per_byte (output_bfd, o);
 
-		if ((o->flags & SEC_ELF_REVERSE_COPY))
+		if ((o->flags & SEC_ELF_REVERSE_COPY)
+		    && o->size > address_size)
 		  {
 		    /* Reverse-copy input section to output.  */
+
+		    if (o->reloc_count != 0
+			&& (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;
+		      }
+
 		    do
 		      {
 			todo -= address_size;
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 9dbc8752f87..0af6c60bce5 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2701,6 +2701,16 @@ lang_add_section (lang_statement_list_type *ptr,
       output->block_value = 128;
     }
 
+  /* When a .ctors section is placed in .init_array it must be copied
+     in reverse order.  Similarly for .dtors.  Set that up.  */
+  if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+      && ((startswith (section->name, ".ctors")
+	   && strcmp (output->bfd_section->name, ".init_array") == 0)
+	  || (startswith (section->name, ".dtors")
+	      && strcmp (output->bfd_section->name, ".fini_array") == 0))
+      && (section->name[6] == 0 || section->name[6] == '.'))
+    section->flags |= SEC_ELF_REVERSE_COPY;
+
   if (section->alignment_power > output->bfd_section->alignment_power)
     output->bfd_section->alignment_power = section->alignment_power;
 


-- 
Alan Modra
Australia Development Lab, IBM


More information about the Binutils mailing list