[PATCH 2/3] ELF: Group and sort output note sections by section alignments

H.J. Lu hjl.tools@gmail.com
Mon Oct 1 18:55:00 GMT 2018


To support putting all adjacent SHT_NOTE sections with the same section
alignment into a single PT_NOTE segment, lang_insert_orphan must group
and sort output note sections by section alignments in both output
section list as well as output section statement list.

	PR ld/23658
	* ldlang.c (lang_insert_orphan): Group and sort output note
	sections by section alignments.
---
 ld/ldlang.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 1ac5eb1ee2..1a27787193 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1875,6 +1875,7 @@ lang_insert_orphan (asection *s,
   if (after != NULL && os->bfd_section != NULL)
     {
       asection *snew, *as;
+      bfd_boolean place_after = place->stmt == NULL;
 
       snew = os->bfd_section;
 
@@ -1912,6 +1913,142 @@ lang_insert_orphan (asection *s,
 	  /* Now tack it back on in the right place.  */
 	  bfd_section_list_append (link_info.output_bfd, snew);
 	}
+      else if ((bfd_get_flavour (link_info.output_bfd)
+		== bfd_target_elf_flavour)
+	       && (bfd_get_flavour (s->owner)
+		   == bfd_target_elf_flavour)
+	       && ((elf_section_type (s) == SHT_NOTE
+		    && (s->flags & SEC_LOAD) != 0)
+		   || (elf_section_type (as) == SHT_NOTE
+		       && (as->flags & SEC_LOAD) != 0)))
+	{
+	  /* Make sure that output note sections are grouped and sorted
+	     by alignments when inserting a note section or insert a
+	     section after a note section,  */
+	  asection *sec;
+	  /* A specific section after which the output note section
+	     should be placed.  */
+	  asection *after_sec;
+	  /* True if we need to insert the orphan section after a
+	     specific section to maintain output note section order.  */
+	  bfd_boolean after_sec_note;
+
+	  /* Group and sort output note section by alignments in
+	     ascending order.  */
+	  after_sec = NULL;
+	  if (elf_section_type (s) == SHT_NOTE
+	      && (s->flags & SEC_LOAD) != 0)
+	    {
+	      /* Search forward for the last output note section
+		 with equal or larger alignments.  */
+	      asection *first_note = NULL;
+
+	      for (sec = as;
+		   (sec != NULL
+		    && !bfd_is_abs_section (sec));
+		   sec = sec->next)
+		if (sec != snew
+		    && elf_section_type (sec) == SHT_NOTE
+		    && (sec->flags & SEC_LOAD) != 0)
+		  {
+		    if (!first_note)
+		      first_note = sec;
+		    if (sec->alignment_power >= s->alignment_power)
+		      after_sec = sec;
+		  }
+
+	      if (after_sec)
+		after_sec_note = TRUE;
+	      else
+		{
+		  /* Search backward for the first output note section
+		     as well as the last output note section with equal
+		     or larger alignments.  */
+		  after_sec = NULL;
+		  for (sec = as;
+		       (sec != NULL
+			&& !bfd_is_abs_section (sec));
+		       sec = sec->prev)
+		    if (sec != snew
+			&& elf_section_type (sec) == SHT_NOTE
+			&& (sec->flags & SEC_LOAD) != 0)
+		      {
+			first_note = sec;
+			if (!after_sec
+			    && sec->alignment_power >= s->alignment_power)
+			  after_sec = sec;
+		      }
+
+		  /* If this will be the first note section, it can be
+		     placed at the default location.  */
+		  after_sec_note = first_note != NULL;
+		  if (after_sec == NULL && after_sec_note)
+		    {
+		      /* If all output note sections have smaller
+			 alignments, place the section before all
+			 output note sections.  AFTER_SEC will be
+			 NULL if FIRST_NOTE is the first output
+			 section.  */
+		      after_sec = first_note->prev;
+		    }
+		}
+	    }
+	  else
+	    {
+	      /* Don't place non-note sections in the middle of note
+		 sections.  */
+	      after_sec_note = TRUE;
+	      after_sec = as;
+	      for (sec = as->next;
+		   (sec != NULL
+		    && !bfd_is_abs_section (sec));
+		   sec = sec->next)
+		if (elf_section_type (sec) == SHT_NOTE
+		    && (sec->flags & SEC_LOAD) != 0)
+		  after_sec = sec;
+	    }
+
+	  if (after_sec_note)
+	    {
+	      if (after_sec)
+		{
+		  /* Insert OS after AFTER_SEC output statement.  */
+		  lang_output_section_statement_type *stmt;
+		  for (stmt = after;
+		       stmt != NULL;
+		       stmt = stmt->next)
+		    if (stmt->bfd_section == after_sec)
+		      {
+			place_after = TRUE;
+			after = stmt;
+			break;
+		      }
+		}
+
+	      if (after_sec == NULL || after_sec->next != snew)
+		{
+		  /* Unlink the section.  */
+		  bfd_section_list_remove (link_info.output_bfd, snew);
+
+		  /* Place SNEW after AFTER_SEC.  If AFTER_SEC is NULL,
+		     prepend SNEW.  */
+		  if (after_sec)
+		    bfd_section_list_insert_after (link_info.output_bfd,
+						   after_sec, snew);
+		  else
+		    bfd_section_list_prepend (link_info.output_bfd, snew);
+		}
+	    }
+	  else if (as != snew && as->prev != snew)
+	    {
+	      /* Unlink the section.  */
+	      bfd_section_list_remove (link_info.output_bfd, snew);
+
+	      /* Now tack it back on in the right place.  */
+	      bfd_section_list_insert_before (link_info.output_bfd,
+					      as, snew);
+	    }
+	}
       else if (as != snew && as->prev != snew)
 	{
 	  /* Unlink the section.  */
@@ -1938,7 +2075,8 @@ lang_insert_orphan (asection *s,
 	{
 	  lang_output_section_statement_type *newly_added_os;
 
-	  if (place->stmt == NULL)
+	  /* Place OS after AFTER if AFTER_NOTE is TRUE.  */
+	  if (place_after)
 	    {
 	      lang_statement_union_type **where = insert_os_after (after);
 
-- 
2.17.1



More information about the Binutils mailing list