From: "H.J. Lu" <hjl.tools@gmail.com>
To: binutils@sourceware.org
Cc: goldstein.w.n@gmail.com
Subject: [PATCH 2/4] elf: Add _bfd_elf_mmap_section and _bfd_elf_munmap_section_contents
Date: Tue, 5 Mar 2024 09:00:55 -0800 [thread overview]
Message-ID: <20240305170057.292800-3-hjl.tools@gmail.com> (raw)
In-Reply-To: <20240305170057.292800-1-hjl.tools@gmail.com>
Add _bfd_elf_mmap_section and _bfd_elf_munmap_section_contents to mmap
in sections. A backend must opt-in to use mmap. It should replace all
usages of bfd_malloc_and_get_section and free with _bfd_elf_mmap_section
and _bfd_elf_munmap_section_contents on section contents.
* compress.c (bfd_get_full_section_contents): Don't allocate
buffer if mmapped_p is true.
* elf-bfd.h (elf_backend_data): Add use_mmap.
(_bfd_elf_mmap_section): New.
(_bfd_elf_munmap_section_contents): Likewise.
* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Replace
bfd_malloc_and_get_section and free with
_bfd_elf_mmap_section and _bfd_elf_munmap_section_contents on
section contents.
* elf-sframe.c (_bfd_elf_parse_sframe): Likewise.
* elf.c: Include <sys/mman.h> if HAVE_MMAP is defined.
(_bfd_elf_make_section_from_shdr): Replace
bfd_malloc_and_get_section and free with
_bfd_elf_mmap_section and _bfd_elf_munmap_section_contents on
section contents.
(_bfd_elf_print_private_bfd_data): Likewise.
(_bfd_elf_mmap_section): New.
(_bfd_elf_munmap_section_contents): Likewise.
* elf32-i386.c (elf_i386_scan_relocs): Replace
bfd_malloc_and_get_section and free with
_bfd_elf_mmap_section and _bfd_elf_munmap_section_contents on
section contents.
* elf64-x86-64.c (elf_x86_64_scan_relocs): Likewise.
(elf_x86_64_get_synthetic_symtab): Likewise.
* elfcode.h (elf_checksum_contents): Likewise.
* elflink.c (elf_link_add_object_symbols): Likewise.
(bfd_elf_get_bfd_needed_list): Likewise.
* elfxx-target.h (elf_backend_use_mmap): New.
(elfNN_bed): Add elf_backend_use_mmap.
* elfxx-x86.c (elf_x86_size_or_finish_relative_reloc): Replace
bfd_malloc_and_get_section and free with
_bfd_elf_mmap_section and _bfd_elf_munmap_section_contents on
section contents.
(_bfd_x86_elf_get_synthetic_symtab): Replace free with
_bfd_elf_munmap_section_contents.
* elfxx-x86.h (elf_backend_use_mmap): New.
* libbfd.c (_bfd_generic_get_section_contents): Call
bfd_mmap_local for mmapped_p.
* opncls.c (_bfd_delete_bfd): Also munmap section contents.
* section.c (asection): Add mmapped_p, contents_addr and
contents_size.
(BFD_FAKE_SECTION): Updated.
(bfd_malloc_and_get_section): Add a sanity check for not
mmapped_p.
* bfd-in2.h: Regenerated.
---
bfd/bfd-in2.h | 22 +++++++++---
bfd/compress.c | 2 +-
bfd/elf-bfd.h | 11 ++++++
bfd/elf-eh-frame.c | 4 +--
bfd/elf-sframe.c | 4 +--
bfd/elf.c | 88 +++++++++++++++++++++++++++++++++++++++++++---
bfd/elf32-i386.c | 6 ++--
bfd/elf64-x86-64.c | 10 +++---
bfd/elfcode.h | 7 ++--
bfd/elflink.c | 12 +++----
bfd/elfxx-target.h | 6 +++-
bfd/elfxx-x86.c | 7 ++--
bfd/elfxx-x86.h | 1 +
bfd/libbfd.c | 57 ++++++++++++++++++++++++++++--
bfd/opncls.c | 5 +++
bfd/section.c | 24 ++++++++++---
16 files changed, 223 insertions(+), 43 deletions(-)
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 856cb625997..dbf439a9fa3 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -688,6 +688,9 @@ typedef struct bfd_section
/* Nonzero if this section uses RELA relocations, rather than REL. */
unsigned int use_rela_p:1;
+ /* Nonzero if this section contents are mmapped, rather than malloced. */
+ unsigned int mmapped_p:1;
+
/* Bits used by various backends. The generic code doesn't touch
these fields. */
@@ -826,6 +829,15 @@ typedef struct bfd_section
regions is enabled. */
struct bfd_section *already_assigned;
+ /* If the mmapped_p flag is set, this points to the actual mmapped
+ address of contents. If it is set to NULL, contents isn't
+ mmapped. */
+ void *contents_addr;
+
+ /* If the mmapped_p flag is set, this is the actual mmapped size of
+ contents. */
+ size_t contents_size;
+
/* Explicitly specified section type, if non-zero. */
unsigned int type;
@@ -975,8 +987,8 @@ discarded_section (const asection *sec)
/* linker_mark, linker_has_input, gc_mark, decompress_status, */ \
0, 0, 1, 0, \
\
- /* segment_mark, sec_info_type, use_rela_p, */ \
- 0, 0, 0, \
+ /* segment_mark, sec_info_type, use_rela_p, mmapped_p, */ \
+ 0, 0, 0, 0, \
\
/* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */ \
0, 0, 0, 0, 0, 0, \
@@ -1002,8 +1014,10 @@ discarded_section (const asection *sec)
/* symbol, symbol_ptr_ptr, */ \
(struct bfd_symbol *) SYM, &SEC.symbol, \
\
- /* map_head, map_tail, already_assigned, type */ \
- { NULL }, { NULL }, NULL, 0 \
+ /* map_head, map_tail, already_assigned, contents_addr, */ \
+ { NULL }, { NULL }, NULL, NULL, \
+ /* contents_size, type */ \
+ 0, 0 \
\
}
diff --git a/bfd/compress.c b/bfd/compress.c
index 8bc44de813b..6c211843e60 100644
--- a/bfd/compress.c
+++ b/bfd/compress.c
@@ -749,7 +749,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
switch (compress_status)
{
case COMPRESS_SECTION_NONE:
- if (p == NULL)
+ if (p == NULL && !sec->mmapped_p)
{
p = (bfd_byte *) bfd_malloc (allocsz);
if (p == NULL)
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 3ed22fa6c52..f99b04e460c 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1775,6 +1775,12 @@ struct elf_backend_data
/* True if the 64-bit Linux PRPSINFO structure's `pr_uid' and `pr_gid'
members use a 16-bit data type. */
unsigned linux_prpsinfo64_ugid16 : 1;
+
+ /* True if the backend can use mmap to map in all input section
+ contents. All bfd_malloc_and_get_section and free usages on
+ section contents must be replaced by _bfd_elf_mmap_section and
+ _bfd_elf_munmap_section_contents. */
+ unsigned use_mmap : 1;
};
/* Information about reloc sections associated with a bfd_elf_section_data
@@ -3126,6 +3132,11 @@ extern bool _bfd_elf_maybe_set_textrel
extern bool _bfd_elf_add_dynamic_tags
(bfd *, struct bfd_link_info *, bool);
+extern bool _bfd_elf_mmap_section
+ (bfd *abfd, asection *section, bfd_byte **buf);
+extern void _bfd_elf_munmap_section_contents
+ (asection *, void *);
+
/* Large common section. */
extern asection _bfd_elf_large_com_section;
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 9a504234163..f9836f3ea14 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -618,7 +618,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
/* Read the frame unwind information from abfd. */
- REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
+ REQUIRE (_bfd_elf_mmap_section (abfd, sec, &ehbuf));
/* If .eh_frame section size doesn't fit into int, we cannot handle
it (it would need to use 64-bit .eh_frame format anyway). */
@@ -1052,7 +1052,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
hdr_info->u.dwarf.table = false;
free (sec_info);
success:
- free (ehbuf);
+ _bfd_elf_munmap_section_contents (sec, ehbuf);
free (local_cies);
#undef REQUIRE
}
diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c
index bfc875cd9fc..9a271d414b9 100644
--- a/bfd/elf-sframe.c
+++ b/bfd/elf-sframe.c
@@ -208,7 +208,7 @@ _bfd_elf_parse_sframe (bfd *abfd,
}
/* Read the SFrame stack trace information from abfd. */
- if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf))
+ if (!_bfd_elf_mmap_section (abfd, sec, &sfbuf))
goto fail_no_free;
/* Decode the buffer and keep decoded contents for later use.
@@ -241,7 +241,7 @@ fail_no_free:
abfd, sec);
return false;
success:
- free (sfbuf);
+ _bfd_elf_munmap_section_contents (sec, sfbuf);
return true;
}
diff --git a/bfd/elf.c b/bfd/elf.c
index 173605f294d..587788c4f1b 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -45,6 +45,10 @@ SECTION
#include "safe-ctype.h"
#include "elf-linux-core.h"
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
#ifdef CORE_HEADER
#include CORE_HEADER
#endif
@@ -1150,12 +1154,12 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
{
bfd_byte *contents;
- if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
+ if (!_bfd_elf_mmap_section (abfd, newsect, &contents))
return false;
elf_parse_notes (abfd, (char *) contents, hdr->sh_size,
hdr->sh_offset, hdr->sh_addralign);
- free (contents);
+ _bfd_elf_munmap_section_contents (newsect, contents);
}
if ((newsect->flags & SEC_ALLOC) != 0)
@@ -1735,7 +1739,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
fprintf (f, _("\nDynamic Section:\n"));
- if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
+ if (!_bfd_elf_mmap_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
@@ -1857,7 +1861,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
fprintf (f, "\n");
}
- free (dynbuf);
+ _bfd_elf_munmap_section_contents (s, dynbuf);
dynbuf = NULL;
}
@@ -1914,7 +1918,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
return true;
error_return:
- free (dynbuf);
+ _bfd_elf_munmap_section_contents (s, dynbuf);
return false;
}
@@ -14422,3 +14426,77 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
return result;
}
+
+/* Mmap in section contents. */
+
+bool
+_bfd_elf_mmap_section (bfd *abfd, sec_ptr sec, bfd_byte **buf)
+{
+#ifdef HAVE_MMAP
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ if (bed->use_mmap
+ && sec->compress_status == COMPRESS_SECTION_NONE
+ && (sec->flags & SEC_LINKER_CREATED) == 0)
+ {
+ /* Use mmap only if section size >= the minimum mmap section
+ size. */
+ size_t readsz = bfd_get_section_limit_octets (abfd, sec);
+ size_t allocsz = bfd_get_section_alloc_size (abfd, sec);
+ if (readsz == allocsz && readsz >= _bfd_minimum_mmap_size)
+ {
+ if (sec->contents != NULL)
+ {
+ if (!sec->mmapped_p)
+ abort ();
+ *buf = sec->contents;
+ return true;
+ }
+ if (sec->mmapped_p)
+ abort ();
+ sec->mmapped_p = 1;
+ }
+ }
+#endif
+ *buf = NULL;
+ bool ret = bfd_get_full_section_contents (abfd, sec, buf);
+ if (ret && sec->mmapped_p)
+ *buf = sec->contents;
+ return ret;
+}
+
+/* Munmap section contents. */
+
+void
+_bfd_elf_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED,
+ void *contents)
+{
+ /* NB: Since _bfd_elf_munmap_section_contents is called like free,
+ CONTENTS may be NULL. */
+ if (contents == NULL)
+ return;
+
+#ifdef HAVE_MMAP
+ if (sec->mmapped_p)
+ {
+ /* NB: Don't free CONTENTS if it has been cached. */
+ if (elf_section_data (sec)->this_hdr.contents == contents)
+ return;
+
+ /* When bfd_mmap_local returns (void *) -1 on an unknown input,
+ CONTENTS is malloced and CONTENTS_ADDR is set to NULL. */
+ if (sec->contents_addr != NULL)
+ {
+ /* NB: CONTENTS_ADDR and CONTENTS_SIZE must be valid. */
+ if (munmap (sec->contents_addr, sec->contents_size) != 0)
+ abort ();
+ sec->mmapped_p = 0;
+ sec->contents = NULL;
+ sec->contents_addr = NULL;
+ sec->contents_size = 0;
+ return;
+ }
+ }
+#endif
+
+ free (contents);
+}
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 703a48c2c0a..8aa1533d0ba 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1499,7 +1499,7 @@ elf_i386_scan_relocs (bfd *abfd,
/* Get the section contents. */
if (elf_section_data (sec)->this_hdr.contents != NULL)
contents = elf_section_data (sec)->this_hdr.contents;
- else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
+ else if (!_bfd_elf_mmap_section (abfd, sec, &contents))
{
sec->check_relocs_failed = 1;
return false;
@@ -1933,7 +1933,7 @@ elf_i386_scan_relocs (bfd *abfd,
if (elf_section_data (sec)->this_hdr.contents != contents)
{
if (!converted && !_bfd_link_keep_memory (info))
- free (contents);
+ _bfd_elf_munmap_section_contents (sec, contents);
else
{
/* Cache the section contents for elf_link_input_bfd if any
@@ -1951,7 +1951,7 @@ elf_i386_scan_relocs (bfd *abfd,
error_return:
if (elf_section_data (sec)->this_hdr.contents != contents)
- free (contents);
+ _bfd_elf_munmap_section_contents (sec, contents);
sec->check_relocs_failed = 1;
return false;
}
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 3300a2017bd..f1e06040a5a 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2057,7 +2057,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
/* Get the section contents. */
if (elf_section_data (sec)->this_hdr.contents != NULL)
contents = elf_section_data (sec)->this_hdr.contents;
- else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
+ else if (!_bfd_elf_mmap_section (abfd, sec, &contents))
{
sec->check_relocs_failed = 1;
return false;
@@ -2591,7 +2591,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
if (elf_section_data (sec)->this_hdr.contents != contents)
{
if (!converted && !_bfd_link_keep_memory (info))
- free (contents);
+ _bfd_elf_munmap_section_contents (sec, contents);
else
{
/* Cache the section contents for elf_link_input_bfd if any
@@ -2609,7 +2609,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
error_return:
if (elf_section_data (sec)->this_hdr.contents != contents)
- free (contents);
+ _bfd_elf_munmap_section_contents (sec, contents);
sec->check_relocs_failed = 1;
return false;
}
@@ -5274,7 +5274,7 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
continue;
/* Get the PLT section contents. */
- if (!bfd_malloc_and_get_section (abfd, plt, &plt_contents))
+ if (!_bfd_elf_mmap_section (abfd, plt, &plt_contents))
break;
/* Check what kind of PLT it is. */
@@ -5367,7 +5367,7 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
if (plt_type == plt_unknown)
{
- free (plt_contents);
+ _bfd_elf_munmap_section_contents (plt, plt_contents);
continue;
}
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 1e0784611bc..6c2ad904fc0 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1195,6 +1195,7 @@ elf_checksum_contents (bfd *abfd,
Elf_Internal_Shdr i_shdr;
Elf_External_Shdr x_shdr;
bfd_byte *contents, *free_contents;
+ asection *sec = NULL;
i_shdr = *i_shdrp[count];
i_shdr.sh_offset = 0;
@@ -1210,8 +1211,6 @@ elf_checksum_contents (bfd *abfd,
contents = i_shdr.contents;
if (contents == NULL)
{
- asection *sec;
-
sec = bfd_section_from_elf_index (abfd, count);
if (sec != NULL)
{
@@ -1220,7 +1219,7 @@ elf_checksum_contents (bfd *abfd,
{
/* Force rereading from file. */
sec->flags &= ~SEC_IN_MEMORY;
- if (!bfd_malloc_and_get_section (abfd, sec, &free_contents))
+ if (!_bfd_elf_mmap_section (abfd, sec, &free_contents))
continue;
contents = free_contents;
}
@@ -1229,7 +1228,7 @@ elf_checksum_contents (bfd *abfd,
if (contents != NULL)
{
(*process) (contents, i_shdr.sh_size, arg);
- free (free_contents);
+ _bfd_elf_munmap_section_contents (sec, free_contents);
}
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 42029f29f7a..47fb890f94f 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -4426,10 +4426,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
unsigned int elfsec;
unsigned long shlink;
- if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
+ if (!_bfd_elf_mmap_section (abfd, s, &dynbuf))
{
error_free_dyn:
- free (dynbuf);
+ _bfd_elf_munmap_section_contents (s, dynbuf);
goto error_return;
}
@@ -4535,7 +4535,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
elf_tdata (abfd)->is_pie = (dyn.d_un.d_val & DF_1_PIE) != 0;
}
- free (dynbuf);
+ _bfd_elf_munmap_section_contents (s, dynbuf);
}
/* DT_RUNPATH overrides DT_RPATH. Do _NOT_ bfd_release, as that
@@ -8283,7 +8283,7 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
if (s == NULL || s->size == 0 || (s->flags & SEC_HAS_CONTENTS) == 0)
return true;
- if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
+ if (!_bfd_elf_mmap_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
@@ -8329,12 +8329,12 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
}
}
- free (dynbuf);
+ _bfd_elf_munmap_section_contents (s, dynbuf);
return true;
error_return:
- free (dynbuf);
+ _bfd_elf_munmap_section_contents (s, dynbuf);
return false;
}
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index a7f2fc6e320..cabe3730d18 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -148,6 +148,9 @@
#ifndef elf_backend_strtab_flags
#define elf_backend_strtab_flags 0
#endif
+#ifndef elf_backend_use_mmap
+#define elf_backend_use_mmap false
+#endif
#define bfd_elfNN_bfd_debug_info_start _bfd_void_bfd
#define bfd_elfNN_bfd_debug_info_end _bfd_void_bfd
@@ -972,7 +975,8 @@ static const struct elf_backend_data elfNN_bed =
elf_backend_extern_protected_data,
elf_backend_always_renumber_dynsyms,
elf_backend_linux_prpsinfo32_ugid16,
- elf_backend_linux_prpsinfo64_ugid16
+ elf_backend_linux_prpsinfo64_ugid16,
+ elf_backend_use_mmap
};
/* Forward declaration for use when initialising alternative_target field. */
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 508fd771da3..ed9822628a6 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1566,9 +1566,8 @@ elf_x86_size_or_finish_relative_reloc
= elf_section_data (sec)->this_hdr.contents;
else
{
- if (!bfd_malloc_and_get_section (sec->owner,
- sec,
- &contents))
+ if (!_bfd_elf_mmap_section (sec->owner,
+ sec, &contents))
info->callbacks->einfo
/* xgettext:c-format */
(_("%F%P: %pB: failed to allocate memory for section `%pA'\n"),
@@ -3789,7 +3788,7 @@ _bfd_x86_elf_get_synthetic_symtab (bfd *abfd,
count = n;
for (j = 0; plts[j].name != NULL; j++)
- free (plts[j].contents);
+ _bfd_elf_munmap_section_contents (plts[j].sec, plts[j].contents);
free (dynrelbuf);
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index b3af9b841ba..8680e3c29b5 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -960,6 +960,7 @@ extern void _bfd_x86_elf_link_report_relative_reloc
_bfd_elf_x86_size_relative_relocs
#define elf_backend_finish_relative_relocs \
_bfd_elf_x86_finish_relative_relocs
+#define elf_backend_use_mmap true
#define ELF_P_ALIGN ELF_MINPAGESIZE
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index e1bb9fb6117..21550f2914d 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -1202,6 +1202,19 @@ _bfd_generic_get_section_contents (bfd *abfd,
return false;
}
+#ifdef HAVE_MMAP
+ if (section->mmapped_p
+ && (section->contents != NULL || location != NULL))
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: mapped section %pA has non-NULLL buffer"),
+ abfd, section);
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+#endif
+
sz = bfd_get_section_limit_octets (abfd, section);
if (offset + count < count
|| offset + count > sz
@@ -1214,8 +1227,48 @@ _bfd_generic_get_section_contents (bfd *abfd,
return false;
}
- if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
- || bfd_read (location, count, abfd) != count)
+ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
+ return false;
+
+#ifdef HAVE_MMAP
+ if (section->mmapped_p)
+ {
+ if (location != 0)
+ abort ();
+
+ int prot = ((section->reloc_count == 0)
+ ? PROT_READ : PROT_READ | PROT_WRITE);
+
+ location = bfd_mmap_local (abfd, count, prot,
+ §ion->contents_addr,
+ §ion->contents_size);
+
+ if (location == NULL)
+ return false;
+
+ /* Check for the unknown input file. */
+ if (location != (void *) -1)
+ {
+ section->contents = location;
+ return true;
+ }
+
+ /* Malloc the buffer and call bfd_read. */
+ location = (bfd_byte *) bfd_malloc (count);
+ if (location == NULL)
+ {
+ if (bfd_get_error () == bfd_error_no_memory)
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"),
+ abfd, section, (uint64_t) count);
+ return false;
+ }
+ section->contents = location;
+ }
+#endif
+
+ if (bfd_read (location, count, abfd) != count)
return false;
return true;
diff --git a/bfd/opncls.c b/bfd/opncls.c
index d54065e8be9..1dd30a19ac6 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -168,6 +168,11 @@ static void
_bfd_delete_bfd (bfd *abfd)
{
#ifdef HAVE_MMAP
+ asection *sec;
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ if (sec->mmapped_p)
+ munmap (sec->contents_addr, sec->contents_size);
+
struct bfd_mmapped *mmapped, *next;
for (mmapped = abfd->mmapped; mmapped != NULL; mmapped = next)
{
diff --git a/bfd/section.c b/bfd/section.c
index 8cd30e80f2b..c9f7f96662c 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -422,6 +422,9 @@ CODE_FRAGMENT
. {* Nonzero if this section uses RELA relocations, rather than REL. *}
. unsigned int use_rela_p:1;
.
+. {* Nonzero if this section contents are mmapped, rather than malloced. *}
+. unsigned int mmapped_p:1;
+.
. {* Bits used by various backends. The generic code doesn't touch
. these fields. *}
.
@@ -560,6 +563,15 @@ CODE_FRAGMENT
. regions is enabled. *}
. struct bfd_section *already_assigned;
.
+. {* If the mmapped_p flag is set, this points to the actual mmapped
+. address of contents. If it is set to NULL, contents isn't
+. mmapped. *}
+. void *contents_addr;
+.
+. {* If the mmapped_p flag is set, this is the actual mmapped size of
+. contents. *}
+. size_t contents_size;
+.
. {* Explicitly specified section type, if non-zero. *}
. unsigned int type;
.
@@ -711,8 +723,8 @@ EXTERNAL
. {* linker_mark, linker_has_input, gc_mark, decompress_status, *} \
. 0, 0, 1, 0, \
. \
-. {* segment_mark, sec_info_type, use_rela_p, *} \
-. 0, 0, 0, \
+. {* segment_mark, sec_info_type, use_rela_p, mmapped_p, *} \
+. 0, 0, 0, 0, \
. \
. {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, *} \
. 0, 0, 0, 0, 0, 0, \
@@ -738,8 +750,10 @@ EXTERNAL
. {* symbol, symbol_ptr_ptr, *} \
. (struct bfd_symbol *) SYM, &SEC.symbol, \
. \
-. {* map_head, map_tail, already_assigned, type *} \
-. { NULL }, { NULL }, NULL, 0 \
+. {* map_head, map_tail, already_assigned, contents_addr, *} \
+. { NULL }, { NULL }, NULL, NULL, \
+. {* contents_size, type *} \
+. 0, 0 \
. \
. }
.
@@ -1625,6 +1639,8 @@ DESCRIPTION
bool
bfd_malloc_and_get_section (bfd *abfd, sec_ptr sec, bfd_byte **buf)
{
+ if (sec->mmapped_p)
+ abort ();
*buf = NULL;
return bfd_get_full_section_contents (abfd, sec, buf);
}
--
2.44.0
next prev parent reply other threads:[~2024-03-05 17:01 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-05 17:00 [PATCH 0/4] elf: Use mmap to map in section contents H.J. Lu
2024-03-05 17:00 ` [PATCH 1/4] elf: Use mmap to map in read-only sections H.J. Lu
2024-03-05 17:00 ` H.J. Lu [this message]
2024-03-05 17:00 ` [PATCH 3/4] elf: Use mmap to map in symbol and relocation tables H.J. Lu
2024-03-05 17:00 ` [PATCH 4/4] elf: Don't cache symbol nor relocation tables with mmap H.J. Lu
2024-03-05 17:03 ` [PATCH 0/4] elf: Use mmap to map in section contents Noah Goldstein
2024-03-06 0:50 ` Alan Modra
2024-03-06 16:16 ` H.J. Lu
2024-03-06 20:51 ` H.J. Lu
2024-03-06 4:45 ` Sam James
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240305170057.292800-3-hjl.tools@gmail.com \
--to=hjl.tools@gmail.com \
--cc=binutils@sourceware.org \
--cc=goldstein.w.n@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).