From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id CCD35385801C for ; Wed, 6 Mar 2024 23:24:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CCD35385801C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CCD35385801C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::436 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709767450; cv=none; b=xyxbMGNwDcQVTrhNtBKXl7Bb1kyoIFrHMBOLZgEw+jC/QhlyNML7w9zp3C7sMqQivk5aB5asr6QEfZtTyiPPaDi2WZSwHrFtVNUN5Ew2xybRaFj8r5Y+PGRgWXt34o3b86q5jUvNOxbuHKPRu/qqJbuMwbud6w+X6/rhylbnjrk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709767450; c=relaxed/simple; bh=H+LPdJfR7i4uRJWfiOvve1DOm5+oQFoa0nPV7emF/5U=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=tx9KG6zGCHtk2ONP8BZLyfU7gvflgFoc/vTqDB4Jca3RJRq1sc4Lc+BqQGS8pycD/zFGH0RXZ60O7i8w0eyYnF1m3nAa9HEx9kTG7+/uZstTMxIAW3EiaGenvMbHYEnzsvh6pCmANRUGH75Yir+w0BhA2SxchqvhurUVPtvIHV8= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-6e6092a84f4so233004b3a.0 for ; Wed, 06 Mar 2024 15:24:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1709767446; x=1710372246; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NFdfv6Guy6SljxRLuKBKMk5s52/FWVS5EsHHxNC+EH8=; b=T9bYrbCN38Y+7Rnyc9spbXklf6/eJVvfSIfFEZRM9DLsp8eJNaveDK7XG+1FtQccx+ r+Lu5g2H/GvHoBMAaUHfTtxdYVgIqHu1Oqy+PMQhcpqcgp6w3EcamC7kXPQhXtrmd/tS cPuqnIScZO75Z7mSrSdm1fjWHw43/hs3XYGMkCNX7x6FTv+K64J2oy47vW3ppPlRYjV6 A+uc8/tpu8aSl9fVi8+W0D9fy8d5NXvTa/PyX4RP8wpEScicfMaAvUKHB2fSWUZU+HyJ DTSqs4mFVNZmgnHWaS82Lzz6VPF+edyHf2ulF4xiM0RyU17It6gsAgUtDoCjtH5zPRxQ 1A3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709767446; x=1710372246; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NFdfv6Guy6SljxRLuKBKMk5s52/FWVS5EsHHxNC+EH8=; b=bjJBSBJo8uG7rM9eic2yd4LO5TN0F+TEPF1I2pw6an9cYj2OeT5Qvy0mXbXqHO/qqm JzFXJ5SADUNxKSIk7bkCQFf+XkyilPV7si6TfFmj3boMWEYzqhP/tOi2+4uw7uZpLaIr T0dDNl4ic+2toP2bMk++lM4P/KZf/TqgHpbkmMw9iJHl3UICPWkMyMzJ5ZSyTuFYjA0a dz4JZHEtC+JWC9Mze79hnZKDwXF2KFB5n1QRN1xmoioodBjGGNfmitfv16ZqvyBcUq4b gSjWpFMTbGo+1QrrC2xRPtoCy+DKKh6nFCP/LwE1lffASl9QXMyM6M9lUYgT7J3K0rP4 pCHg== X-Gm-Message-State: AOJu0YwweptzgV2PQ87Y/ePAVLs+DeXZSAH/3FUmGT7NY/XzTz1tO8wO EMM2irTn4y2r5Us4W4LQUS4O8YoBVMle77TmOXFIlpzO7EGorc62/dgXOyaE X-Google-Smtp-Source: AGHT+IFK5Qa6e7GiQ7jSYHPhri5WDnZD3zJ4pZNlJ1Z2qexkUZEdhJMV+Bh/QUmfz9/PMusQACWXJg== X-Received: by 2002:a05:6a00:a8e:b0:6e6:211e:185a with SMTP id b14-20020a056a000a8e00b006e6211e185amr10955616pfl.20.1709767445553; Wed, 06 Mar 2024 15:24:05 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id h10-20020aa79f4a000000b006e647716b6esm2469779pfr.149.2024.03.06.15.24.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Mar 2024 15:24:02 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id D68047406C7; Wed, 6 Mar 2024 15:24:01 -0800 (PST) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, amodra@gmail.com Subject: [PATCH v4 4/6] elf: Add _bfd_elf_mmap_section and _bfd_elf_munmap_section_contents Date: Wed, 6 Mar 2024 15:23:59 -0800 Message-ID: <20240306232401.1408530-5-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240306232401.1408530-1-hjl.tools@gmail.com> References: <20240306232401.1408530-1-hjl.tools@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3019.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_ABUSEAT,RCVD_IN_DNSWL_NONE,RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Add _bfd_elf_mmap_section and _bfd_elf_munmap_section_contents to avoid reading input sections twice. A backend must opt-in to use mmap. It should replace bfd_malloc_and_get_section with _bfd_elf_mmap_section and free with _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_section_data): Add contents_addr and contents_size. (_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 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: Include "elf-bfd.h". (_bfd_generic_get_section_contents): Call bfd_mmap_local for mmapped_p. * opncls.c (_bfd_delete_bfd): Also munmap ELF section contents. * section.c (asection): Add mmapped_p. (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 | 7 ++-- bfd/compress.c | 2 +- bfd/elf-bfd.h | 20 +++++++++++ bfd/elf-eh-frame.c | 4 +-- bfd/elf-sframe.c | 4 +-- bfd/elf.c | 89 +++++++++++++++++++++++++++++++++++++++++++--- 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 | 59 ++++++++++++++++++++++++++++-- bfd/opncls.c | 9 +++++ bfd/section.c | 9 +++-- 16 files changed, 213 insertions(+), 39 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 544422a9522..dc6bceb6a96 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. */ @@ -975,8 +978,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, \ 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 c5d325435b6..da7c5208017 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 @@ -1856,6 +1862,15 @@ struct bfd_elf_section_data /* Link from a text section to its .eh_frame_entry section. */ asection *eh_frame_entry; + /* 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; + /* TRUE if the section has secondary reloc sections associated with it. FIXME: In the future it might be better to change this into a list of secondary reloc sections, making lookup easier and faster. */ @@ -3124,6 +3139,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 1c905762704..e2e31a93950 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -45,6 +45,10 @@ SECTION #include "safe-ctype.h" #include "elf-linux-core.h" +#ifdef USE_MMAP +#include +#endif + #ifdef CORE_HEADER #include CORE_HEADER #endif @@ -1149,12 +1153,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) @@ -1734,7 +1738,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); @@ -1856,7 +1860,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; } @@ -1913,7 +1917,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; } @@ -14418,3 +14422,78 @@ _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 USE_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 USE_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 (elf_section_data (sec)->contents_addr != 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; + 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 1e6992b5793..89e3d36adb2 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 @@ -974,7 +977,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 237f91e5c97..c847c4f0180 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -21,6 +21,7 @@ #include "sysdep.h" #include "bfd.h" +#include "elf-bfd.h" #include "libbfd.h" #include "objalloc.h" @@ -1202,6 +1203,19 @@ _bfd_generic_get_section_contents (bfd *abfd, return false; } +#ifdef USE_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 +1228,49 @@ _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 USE_MMAP + if (section->mmapped_p) + { + if (location != 0 + || bfd_get_flavour (abfd) != bfd_target_elf_flavour) + abort (); + + int prot = ((section->reloc_count == 0) + ? PROT_READ : PROT_READ | PROT_WRITE); + + location = bfd_mmap_local + (abfd, count, prot, &elf_section_data (section)->contents_addr, + &elf_section_data (section)->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 ac74607bac0..582828ab27f 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -168,6 +168,15 @@ static void _bfd_delete_bfd (bfd *abfd) { #ifdef USE_MMAP + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) + { + asection *sec; + for (sec = abfd->sections; sec != NULL; sec = sec->next) + if (sec->mmapped_p) + munmap (elf_section_data (sec)->contents_addr, + elf_section_data (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..604105b39c4 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. *} . @@ -711,8 +714,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, \ @@ -1625,6 +1628,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