From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by sourceware.org (Postfix) with ESMTPS id 88A46385842F for ; Tue, 5 Mar 2024 17:01:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 88A46385842F 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 88A46385842F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1035 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709658067; cv=none; b=spEhHZxiA8QAhRB0Csb5UCqduq0GEUAHvdhXFI1tiu/37uyAeX5/vFmonFCwMrN3gK1bumIIPbRcOcDJ3da00zxk281ceO2zh3BVwDpbXlhY/mMqIxNACEPA+MlvsttCU2yCYVGEnAwlx7l/luexF1/u0z5qesFQMiMS22WGy0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709658067; c=relaxed/simple; bh=aRjT+zPl5yIf/Xwn0KLvbSmDgFteXXvaNbDVvLbl27w=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=loXYlVXvYd+/NNN1PbnXxX7iqSMqvPAd8eWWJija7kWp3FIg2ko9d02fpbxy7nwOq3p13deZDhHcZQVdjOha5BaUrNwi5eBSdWfCvr20eMZ4PLU6gGZRbsvoEDMd4ncE1wzi1bikmWu0Ci+9ot8vYePCghNYayzxYeYQNEt93lw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-29996cc6382so4434138a91.3 for ; Tue, 05 Mar 2024 09:01:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1709658060; x=1710262860; 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=A1xXb2P4yjVZO7eCs4daNRo5/NpU/VtgWxt7+8pYEnk=; b=c5wvBpZ+Q2idp9RW49Wb2jpoKpM0+8GULYGfqf3A5OwR2iYjBwKyKF70xRhJVEkoVw e5A56sUg3c1UVPTdt5PFEmk4zQXq9tJ5C3ecfD/VGRfwsYzxBdmJIHhU1bL5MH0h2lYQ 7Slqw5yuG9il4wqshntA9qfHXwOPG/GpwvVtjZS3qjavx8Kiuu85137+PtFndKimrcdK ME8ezUb+IDjeJeuzWmfgSkmxohrL78vyj1AN2C9iiGb2o9+5q5wMqSgsB68Fc5OqrSyq iRf1KMu6jaYV2/DdCIHmFymnAL2SGCPEj32YZD372EnSComE2s0IvRNrSjk5uRv2ajQ6 n8Zg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709658060; x=1710262860; 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=A1xXb2P4yjVZO7eCs4daNRo5/NpU/VtgWxt7+8pYEnk=; b=EJcdotqP4ptciI5soNhVfdeSNeD18APY8A5ju3okyoTwlZK0ibnGLY7grnik9+I9hG xiTIjBaZ5llEUCGBNH6jKFPXYUEEFd51c9i8YZHr5UMyj8uFsZ8cOoJAmYU9D/yJtJMV pVxR4wPFFZtlMca8qMzeOnxXsLealpp+ENu3ERN7/enGnuijLFCWWY++8K5IZ0keJEhT D8IjhigM/E8EyoHgGvjOnwTIhP3WDi+WS8K8GzhLDQ5Q+LDrqb2DEA69+q/cWQxvSkCf DGaNhQuCTWYAx5eDiE1urMWeiEtYs/kxutpkUm6pjHiTHqG5cJryim6vLsk/3flZBjsA jcJA== X-Gm-Message-State: AOJu0Yye3Fva0t2rPpvSxUmSyU9EWxMvaN0S//7Tw+RkkOerGV77q8X5 Fno4Sn2ymSlG4vBIWr7Bp6hFpG7CtAjGmCQGC1B/9RvLu//lBgavsfsgUQ/+ X-Google-Smtp-Source: AGHT+IHaBdutuQpv8Uux3Ccwznpmjf7Hdw5J+Pkk8308C4dm4kH9vlEdUYynVehWHoXJOOmGR+GW+A== X-Received: by 2002:a17:90a:d344:b0:29a:8398:b0d6 with SMTP id i4-20020a17090ad34400b0029a8398b0d6mr11150371pjx.9.1709658060160; Tue, 05 Mar 2024 09:01:00 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id q40-20020a17090a17ab00b00298cc4c56cdsm13040478pja.22.2024.03.05.09.00.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 09:00:59 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id 3722774042B; Tue, 5 Mar 2024 09:00:58 -0800 (PST) From: "H.J. Lu" 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 Message-ID: <20240305170057.292800-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240305170057.292800-1-hjl.tools@gmail.com> References: <20240305170057.292800-1-hjl.tools@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3019.7 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 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 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 +#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