[v10,6/6] elf: Add _bfd_elf_link_m[un]map_section_contents

Message ID 20240314132552.83916-7-hjl.tools@gmail.com
State Superseded
Headers
Series elf: Use mmap to map in section contents |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed

Commit Message

H.J. Lu March 14, 2024, 1:25 p.m. UTC
  To copy input section contents, add _bfd_elf_link_mmap_section_contents
and _bfd_elf_link_munmap_section_contents to mmap in the input sections.

	* elf-bfd.h (_bfd_elf_link_mmap_section_contents): New.
	(_bfd_elf_link_munmap_section_contents): Likewise.
	* elf.c (elf_mmap_section_contents): New.
	(_bfd_elf_mmap_section_contents): Use it.
	(_bfd_elf_link_mmap_section_contents): New.
	(_bfd_elf_link_munmap_section_contents): Likewise.
	* elflink.c (elf_link_input_bfd): Call
	_bfd_elf_link_mmap_section_contents instead of
	bfd_get_full_section_contents.  Call
	_bfd_elf_link_munmap_section_contents to munmap the section
	contents.
	(bfd_elf_final_link): When mmap is used, initialize
	max_contents_size to _bfd_minimum_mmap_size and increase it
	for compressed or linker created sections or sections whose
	rawsize != size.
---
 bfd/elf-bfd.h |  4 ++++
 bfd/elf.c     | 57 +++++++++++++++++++++++++++++++++++++++++++++++----
 bfd/elflink.c | 26 +++++++++++++++++------
 3 files changed, 77 insertions(+), 10 deletions(-)
  

Patch

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index b9ec590cd4e..c386af3549f 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -3143,6 +3143,10 @@  extern bool _bfd_elf_mmap_section_contents
   (bfd *abfd, asection *section, bfd_byte **buf);
 extern void _bfd_elf_munmap_section_contents
   (asection *, void *);
+extern bool _bfd_elf_link_mmap_section_contents
+  (bfd *abfd, asection *section, bfd_byte **buf);
+extern void _bfd_elf_link_munmap_section_contents
+  (asection *);
 
 extern bool _bfd_elf_link_keep_memory
   (struct bfd_link_info *);
diff --git a/bfd/elf.c b/bfd/elf.c
index 40440445be1..2ed550d3041 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -14416,10 +14416,12 @@  _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
   return result;
 }
 
-/* Mmap in section contents.  */
+/* Mmap in section contents.  If FINAL_LINK is false, set *BUF to NULL
+   before calling bfd_get_full_section_contents.  */
 
-bool
-_bfd_elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf)
+static bool
+elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf,
+			   bool final_link)
 {
 #ifdef USE_MMAP
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -14443,16 +14445,41 @@  _bfd_elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf)
 	  if (sec->mmapped_p)
 	    abort ();
 	  sec->mmapped_p = 1;
+
+	  /* Never use the preallocated buffer if mmapp is used.  */
+	  *buf = NULL;
 	}
     }
 #endif
-  *buf = NULL;
+  /* NB: When this is called from elf_link_input_bfd, FINAL_LINK is
+     true.  If FINAL_LINK is false, *BUF is set to the preallocated
+     buffer if USE_MMAP is undefined and *BUF is set to NULL if
+     USE_MMAP is defined.  */
+  if (!final_link)
+    *buf = NULL;
   bool ret = bfd_get_full_section_contents (abfd, sec, buf);
   if (ret && sec->mmapped_p)
     *buf = sec->contents;
   return ret;
 }
 
+/* Mmap in section contents.  */
+
+bool
+_bfd_elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf)
+{
+  return elf_mmap_section_contents (abfd, sec, buf, false);
+}
+
+/* Mmap in the full section contents for the final link.  */
+
+bool
+_bfd_elf_link_mmap_section_contents (bfd *abfd, sec_ptr sec,
+				     bfd_byte **buf)
+{
+  return elf_mmap_section_contents (abfd, sec, buf, true);
+}
+
 /* Munmap section contents.  */
 
 void
@@ -14492,3 +14519,25 @@  _bfd_elf_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED,
 
   free (contents);
 }
+
+/* Munmap the full section contents for the final link.  */
+
+void
+_bfd_elf_link_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED)
+{
+#ifdef USE_MMAP
+  if (sec->mmapped_p && elf_section_data (sec)->contents_addr != NULL)
+    {
+      /* When _bfd_elf_link_mmap_section_contents returns CONTENTS as
+	 malloced, CONTENTS_ADDR is set to NULL.  */
+      /* NB: CONTENTS_ADDR and CONTENTS_SIZE must be valid.  */
+      if (munmap (elf_section_data (sec)->contents_addr,
+		  elf_section_data (sec)->contents_size) != 0)
+	abort ();
+      sec->mmapped_p = 0;
+      sec->contents = NULL;
+      elf_section_data (sec)->contents_addr = NULL;
+      elf_section_data (sec)->contents_size = 0;
+    }
+#endif
+}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 04c23b3c7f3..28d587ceeed 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11463,7 +11463,8 @@  elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       else
 	{
 	  contents = flinfo->contents;
-	  if (! bfd_get_full_section_contents (input_bfd, o, &contents))
+	  if (! _bfd_elf_link_mmap_section_contents (input_bfd, o,
+						     &contents))
 	    return false;
 	}
 
@@ -12021,6 +12022,9 @@  elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 	  }
 	  break;
 	}
+
+      /* Munmap the section contents for each input section.  */
+      _bfd_elf_link_munmap_section_contents (o);
     }
 
   return true;
@@ -12459,14 +12463,15 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   /* Count up the number of relocations we will output for each output
      section, so that we know the sizes of the reloc sections.  We
      also figure out some maximum sizes.  */
-  max_contents_size = 0;
 #ifdef USE_MMAP
   /* Mmap is used only if section size >= the minimum mmap section
      size.  The initial value covers all sections smaller than the
      minimum mmap section size.  It may be increased for compressed
      or linker created sections or sections whose rawsize != size.  */
+  max_contents_size = _bfd_minimum_mmap_size;
   max_external_reloc_size = _bfd_minimum_mmap_size;
 #else
+  max_contents_size = 0;
   max_external_reloc_size = 0;
 #endif
   max_internal_reloc_count = 0;
@@ -12502,10 +12507,19 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	      if (sec->flags & SEC_MERGE)
 		merged = true;
 
-	      if (sec->rawsize > max_contents_size)
-		max_contents_size = sec->rawsize;
-	      if (sec->size > max_contents_size)
-		max_contents_size = sec->size;
+#ifdef USE_MMAP
+	      /* Mmap is used only on non-compressed, non-linker created
+		 sections whose rawsize == size.  */
+	      if (sec->compress_status != COMPRESS_SECTION_NONE
+		 || (sec->flags & SEC_LINKER_CREATED) != 0
+		 || sec->rawsize != sec->size)
+#endif
+		{
+		  if (sec->rawsize > max_contents_size)
+		    max_contents_size = sec->rawsize;
+		  if (sec->size > max_contents_size)
+		    max_contents_size = sec->size;
+		}
 
 	      if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
 		  && (sec->owner->flags & DYNAMIC) == 0)