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(-)
@@ -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 *);
@@ -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
+}
@@ -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)