]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf: Add _bfd_elf_link_m[un]map_section_contents
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 11 Mar 2024 16:51:06 +0000 (09:51 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 3 Apr 2024 16:11:03 +0000 (09:11 -0700)
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
bfd/elf.c
bfd/elflink.c

index 01e0da135b9264a77cb374bfe6e09832a661b398..f31244f22270dfcde1f07ba9b7ecb49d4528f642 100644 (file)
@@ -3146,6 +3146,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 *);
 
 /* Large common section.  */
 extern asection _bfd_elf_large_com_section;
index 868abeccddbcbdf1355e71ff834c7e0d632fd36a..9b98d3b8b2ba6972d78e172737d1e3c372d22511 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -14366,10 +14366,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);
@@ -14393,16 +14395,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
@@ -14442,3 +14469,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
+}
index a7b50bfcaf9041d32dd6b6d1858e3bc182d5bc57..2a05299b24dac3101e59845ef165952080e23dd1 100644 (file)
@@ -11486,7 +11486,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;
        }
 
@@ -12047,6 +12048,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;
@@ -12485,13 +12489,17 @@ 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.  max_external_reloc_size covers all relocation sections
-     smaller than the minimum mmap section size.   */
+     size.  The initial max_contents_size 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_external_reloc_size covers all relocation
+     sections smaller than the minimum mmap section 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;
@@ -12527,10 +12535,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)