From patchwork Fri Mar 15 12:24:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 87244 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 941273857735 for ; Fri, 15 Mar 2024 12:27:24 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id 5E61C3858C5E for ; Fri, 15 Mar 2024 12:24:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5E61C3858C5E 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 5E61C3858C5E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505473; cv=none; b=kWL3Khs9zOe0dKTB26fZXdHFl+VvdUhuTHmze6C9Hrp2LHYCxyVL/mzSai2yyIWZUKMmXdvdqrTgI1ixv7TmuMcuwOw52aLq7MRMvm1Mz+AGBZRuM17KEFzUtDoiPJ2eDakCE1VW3uGtNaHxvH96yh7YLOo/kV9BwgCHVCj52gw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505473; c=relaxed/simple; bh=+jnyMc2f4yIw+blArK6ERGeAdg+Sd2cJ9Mhe0FnRnEw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=BssTFcawmM6MRe9UD9AFMIkqi2lB+Rn09dLbMzEC21sQaE0hmFxa4dNjmVMuKFNQn0dilK0un97246SW7Eji6I9U+nacgT7jwBZopHpD+ud7foxd13TmFOBlSBrs20hq3x3q51AkiIplvJ6pzDQL0SryWqFvH1hgFc2gi7JmeoY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-1def59b537cso2614515ad.2 for ; Fri, 15 Mar 2024 05:24:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710505465; x=1711110265; 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=orBT0KACp4P6NJcM0hGDO37dKoUKitUWAjDw+8fd8Zs=; b=MNaUrsLTnxG9XPyYT+b3UqaW55XFmbH+7o0l09CCzlrJ3Mr5/SkDh4OR29EVANUrYF UJemCt75tg2EYDeOcwvZnP09cdBzkjSR9jzRo/rdFhrXqaNn3k5tkSM0uy1QSMhLhz98 I0YriIEJuN/80jg9Y5n7G9N2ICQAiNMOBcxxD99J6Wx6ZLuSya0FYYLytsSUk/Qcicb1 LsmRd/Fb98Q0evGWZbCgDynN7GMF9J2eR+2IoSVWuckXWsenyU1bp6gTl5ISXtcHuF07 4pUsmY1XkC7IVDKpJNe+p5A9VmV8bhjwY0+fgQqB4WF1KHTa7te0zWLOKCVMPjXYymQh E0rQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710505465; x=1711110265; 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=orBT0KACp4P6NJcM0hGDO37dKoUKitUWAjDw+8fd8Zs=; b=lkbxEUeLj7Ha70MvUps54gx4vi3N6fRskds56L/Lj+VtNpEgfdTXnHJFm4WbQsOzhH wiGIJtDJNcvM4fBJdewCsRzaACdJUTPKWsTAWOP/GDy1u5JQsIcWWjNVKMGmopeM4FTT bgfSbf8v9TyGrkozuovu6cHf106JIqnEaCezwrQp5kLM5PgfHUXnYtCurKMH3a752KAw w2alkQ++SumQKdlluPTjoborEWiJP0d6+HIYIISBRxjSLOATvevFdZN/1qqVwDSnSI2d 6AS2DRwmdJCjt5ToIkdUaM++my00Ht1RZuPnqECFvML2bOf3TBrWkeGLxovo2KEJxNZ6 6FzQ== X-Gm-Message-State: AOJu0YwYoDJOaiho7bPnuyqz56saNnZJx6M1Ygs6XyC5kkJmwQoJckmn ZmYlVrJ3MQJtPH3k/2dUPMSQRq0tMYqtBy+Se6+1drEhu+wDQCBj X-Google-Smtp-Source: AGHT+IFE7NZggBywidCgvzZSeRK3eRDbFQ2u2jk/nZ+zm/Zj0SvaaM6mhyPabgTDX012etSXGKrvzA== X-Received: by 2002:a17:902:eb46:b0:1dc:cee2:5ffc with SMTP id i6-20020a170902eb4600b001dccee25ffcmr2873984pli.6.1710505465073; Fri, 15 Mar 2024 05:24:25 -0700 (PDT) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id b1-20020a170902d50100b001dd5cdaaa0fsm3668925plg.250.2024.03.15.05.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 05:24:24 -0700 (PDT) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id 86255740337; Fri, 15 Mar 2024 05:24:23 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, sam@gentoo.org, amodra@gmail.com Subject: [PATCH v11 1/6] elf: Use mmap to map in read-only sections Date: Fri, 15 Mar 2024 05:24:18 -0700 Message-ID: <20240315122423.1963285-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315122423.1963285-1-hjl.tools@gmail.com> References: <20240315122423.1963285-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3020.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org There are many linker input files in LLVM debug build with huge string sections. All these string sections can be treated as read-only. But linker copies all of them into memory which consumes huge amount of memory and slows down linker significantly. Add _bfd_mmap_readonly_persistent and _bfd_mmap_readonly_temporary to mmap in reado-only sections with size >= 4 * page size. NB: All string sections in valid ELF inputs must be null terminated. There is no need to terminate it again and string sections are mmapped as read-only. * bfd.c (bfd_mmapped_entry): New. (bfd_mmapped): Likewise. (bfd): Add mmapped. * bfdwin.c (bfd_get_file_window): Use _bfd_pagesize. * cache.c (cache_bmmap): Remove pagesize_m1 and use pagesize_m1 instead. * elf.c (bfd_elf_get_str_section): Call _bfd_mmap_readonly_persistent instead of _bfd_alloc_and_read. Don't terminate the string section again. (get_hash_table_data): Call _bfd_mmap_readonly_temporary and _bfd_munmap_readonly_temporary instead of _bfd_malloc_and_read and free. (_bfd_elf_get_dynamic_symbols): Call _bfd_mmap_readonly_persistent instead of _bfd_alloc_and_read. Don't terminate the string section again. Call _bfd_mmap_readonly_temporary and _bfd_munmap_readonly_temporary instead of _bfd_malloc_and_read and free. (_bfd_elf_slurp_version_tables): Call _bfd_mmap_readonly_temporary and _bfd_munmap_readonly_temporary instead of _bfd_malloc_and_read and free. * elflink.c (bfd_elf_link_record_dynamic_symbol): Use bfd_malloc to get the unversioned symbol. * libbfd-in.h (_bfd_pagesize): New. (_bfd_pagesize_m1): Likewise. (_bfd_minimum_mmap_size): Likewise. (_bfd_mmap_readonly_persistent): Likewise. (_bfd_mmap_readonly_temporary): Likewise. (_bfd_munmap_readonly_temporary): Likewise. * libbfd.c (bfd_allocate_mmapped_page): New. (_bfd_mmap_readonly_temporary): Likewise. (_bfd_munmap_readonly_temporary): Likewise. (_bfd_mmap_readonly_persistent): Likewise. (_bfd_pagesize): Likewise. (_bfd_pagesize_m1): Likewise. (_bfd_minimum_mmap_size): Likewise. (bfd_init_pagesize): Likewise. * lynx-core.c (lynx_core_file_p): Use _bfd_pagesize. * opncls.c (_bfd_delete_bfd): Munmap tracked mmapped memories. * sysdep.h (MAP_ANONYMOUS): New. Define if undefined. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. --- bfd/bfd-in2.h | 17 ++++++ bfd/bfd.c | 17 ++++++ bfd/bfdwin.c | 8 +-- bfd/cache.c | 7 +-- bfd/elf.c | 79 +++++++++++++++++-------- bfd/elflink.c | 16 ++--- bfd/libbfd-in.h | 29 ++++++++++ bfd/libbfd.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ bfd/libbfd.h | 29 ++++++++++ bfd/lynx-core.c | 2 +- bfd/opncls.c | 12 ++++ bfd/sysdep.h | 4 ++ 12 files changed, 328 insertions(+), 43 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 29602e054da..544422a9522 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1951,6 +1951,20 @@ struct bfd_build_id bfd_byte data[1]; }; +struct bfd_mmapped_entry + { + void *addr; + size_t size; + }; + +struct bfd_mmapped + { + struct bfd_mmapped *next; + unsigned int max_entry; + unsigned int next_entry; + struct bfd_mmapped_entry entries[1]; + }; + struct bfd { /* The filename the application opened the BFD with. */ @@ -2280,6 +2294,9 @@ struct bfd /* For input BFDs, the build ID, if the object has one. */ const struct bfd_build_id *build_id; + + /* For input BFDs, mmapped entries. */ + struct bfd_mmapped *mmapped; }; static inline const char * diff --git a/bfd/bfd.c b/bfd/bfd.c index 54061a34240..8302013f1b4 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -74,6 +74,20 @@ EXTERNAL . bfd_byte data[1]; . }; . +.struct bfd_mmapped_entry +. { +. void *addr; +. size_t size; +. }; +. +.struct bfd_mmapped +. { +. struct bfd_mmapped *next; +. unsigned int max_entry; +. unsigned int next_entry; +. struct bfd_mmapped_entry entries[1]; +. }; +. CODE_FRAGMENT .struct bfd @@ -406,6 +420,9 @@ CODE_FRAGMENT . . {* For input BFDs, the build ID, if the object has one. *} . const struct bfd_build_id *build_id; +. +. {* For input BFDs, mmapped entries. *} +. struct bfd_mmapped *mmapped; .}; . diff --git a/bfd/bfdwin.c b/bfd/bfdwin.c index 2919c71b3cb..73e44635bcb 100644 --- a/bfd/bfdwin.c +++ b/bfd/bfdwin.c @@ -157,7 +157,7 @@ bfd_get_file_window (bfd *abfd, bool writable) { static int ok_to_map = 1; - static size_t pagesize; + size_t pagesize = _bfd_pagesize; bfd_window_internal *i = windowp->i; bfd_size_type size_to_alloc = size; @@ -167,12 +167,6 @@ bfd_get_file_window (bfd *abfd, windowp, windowp->data, (unsigned long) windowp->size, windowp->i, writable); - /* Make sure we know the page size, so we can be friendly to mmap. */ - if (pagesize == 0) - pagesize = getpagesize (); - if (pagesize == 0) - abort (); - if (i == NULL) { i = bfd_zmalloc (sizeof (bfd_window_internal)); diff --git a/bfd/cache.c b/bfd/cache.c index d0e7be293a5..0f994c74239 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -494,10 +494,10 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, #ifdef HAVE_MMAP else { - static uintptr_t pagesize_m1; + uintptr_t pagesize_m1 = _bfd_pagesize_m1; FILE *f; file_ptr pg_offset; - bfd_size_type pg_len; + size_t pg_len; f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); if (f == NULL) @@ -506,9 +506,6 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, return ret; } - if (pagesize_m1 == 0) - pagesize_m1 = getpagesize () - 1; - /* Align. */ pg_offset = offset & ~pagesize_m1; pg_len = (len + (offset - pg_offset) + pagesize_m1) & ~pagesize_m1; diff --git a/bfd/elf.c b/bfd/elf.c index 8bffd3c5141..c80fff47b45 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -289,16 +289,23 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex) in case the string table is not terminated. */ if (shstrtabsize + 1 <= 1 || bfd_seek (abfd, offset, SEEK_SET) != 0 - || (shstrtab = _bfd_alloc_and_read (abfd, shstrtabsize + 1, - shstrtabsize)) == NULL) + || (shstrtab + = _bfd_mmap_readonly_persistent (abfd, shstrtabsize)) == NULL) { /* Once we've failed to read it, make sure we don't keep trying. Otherwise, we'll keep allocating space for the string table over and over. */ i_shdrp[shindex]->sh_size = 0; } - else - shstrtab[shstrtabsize] = '\0'; + else if (shstrtab[shstrtabsize - 1] != '\0') + { + /* It is an error if a string table isn't terminated. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): string table is corrupt"), + abfd, i_shdrp[shindex]->bfd_section); + return NULL; + } i_shdrp[shindex]->contents = shstrtab; } return (char *) shstrtab; @@ -1919,6 +1926,8 @@ get_hash_table_data (bfd *abfd, bfd_size_type number, unsigned char *e_data = NULL; bfd_vma *i_data = NULL; bfd_size_type size; + void *e_data_addr; + size_t e_data_size ATTRIBUTE_UNUSED; if (ent_size != 4 && ent_size != 8) return NULL; @@ -1940,7 +1949,8 @@ get_hash_table_data (bfd *abfd, bfd_size_type number, return NULL; } - e_data = _bfd_malloc_and_read (abfd, size, size); + e_data = _bfd_mmap_readonly_temporary (abfd, size, &e_data_addr, + &e_data_size); if (e_data == NULL) return NULL; @@ -1958,7 +1968,7 @@ get_hash_table_data (bfd *abfd, bfd_size_type number, while (number--) i_data[number] = bfd_get_64 (abfd, e_data + number * ent_size); - free (e_data); + _bfd_munmap_readonly_temporary (e_data_addr, e_data_size); return i_data; } @@ -2007,6 +2017,10 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, size_t verneed_size = 0; size_t extsym_size; const struct elf_backend_data *bed; + void *dynbuf_addr = NULL; + void *esymbuf_addr = NULL; + size_t dynbuf_size = 0; + size_t esymbuf_size = 0; /* Return TRUE if symbol table is bad. */ if (elf_bad_symtab (abfd)) @@ -2024,7 +2038,9 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, if (bfd_seek (abfd, phdr->p_offset, SEEK_SET) != 0) goto error_return; - dynbuf = _bfd_malloc_and_read (abfd, phdr->p_filesz, phdr->p_filesz); + dynbuf_size = phdr->p_filesz; + dynbuf = _bfd_mmap_readonly_temporary (abfd, dynbuf_size, + &dynbuf_addr, &dynbuf_size); if (dynbuf == NULL) goto error_return; @@ -2102,11 +2118,17 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, goto error_return; /* Dynamic string table must be valid until ABFD is closed. */ - strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz + 1, dt_strsz); + strbuf = (char *) _bfd_mmap_readonly_persistent (abfd, dt_strsz); if (strbuf == NULL) goto error_return; - /* Since this is a string table, make sure that it is terminated. */ - strbuf[dt_strsz] = 0; + if (strbuf[dt_strsz - 1] != 0) + { + /* It is an error if a string table is't terminated. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: DT_STRTAB table is corrupt"), abfd); + goto error_return; + } /* Get the real symbol count from DT_HASH or DT_GNU_HASH. Prefer DT_HASH since it is simpler than DT_GNU_HASH. */ @@ -2281,7 +2303,10 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, if (filepos == (file_ptr) -1 || bfd_seek (abfd, filepos, SEEK_SET) != 0) goto error_return; - esymbuf = _bfd_malloc_and_read (abfd, amt, amt); + esymbuf_size = amt; + esymbuf = _bfd_mmap_readonly_temporary (abfd, esymbuf_size, + &esymbuf_addr, + &esymbuf_size); if (esymbuf == NULL) goto error_return; @@ -2325,7 +2350,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, goto error_return; /* DT_VERSYM info must be valid until ABFD is closed. */ - versym = _bfd_alloc_and_read (abfd, amt, amt); + versym = _bfd_mmap_readonly_persistent (abfd, amt); if (dt_verdef) { @@ -2337,8 +2362,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, goto error_return; /* DT_VERDEF info must be valid until ABFD is closed. */ - verdef = _bfd_alloc_and_read (abfd, verdef_size, - verdef_size); + verdef = _bfd_mmap_readonly_persistent (abfd, verdef_size); } if (dt_verneed) @@ -2351,8 +2375,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, goto error_return; /* DT_VERNEED info must be valid until ABFD is closed. */ - verneed = _bfd_alloc_and_read (abfd, verneed_size, - verneed_size); + verneed = _bfd_mmap_readonly_persistent (abfd, verneed_size); } } @@ -2375,8 +2398,8 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr, /* Restore file position for elf_object_p. */ if (bfd_seek (abfd, saved_filepos, SEEK_SET) != 0) res = false; - free (dynbuf); - free (esymbuf); + _bfd_munmap_readonly_temporary (dynbuf_addr, dynbuf_size); + _bfd_munmap_readonly_temporary (esymbuf_addr, esymbuf_size); free (gnubuckets); free (gnuchains); free (mipsxlat); @@ -9435,6 +9458,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver) bfd_byte *contents = NULL; unsigned int freeidx = 0; size_t amt; + void *contents_addr = NULL; + size_t contents_size = 0; if (elf_dynverref (abfd) != 0 || elf_tdata (abfd)->dt_verneed != NULL) { @@ -9471,7 +9496,10 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver) if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0) goto error_return_verref; - contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size); + contents_size = hdr->sh_size; + contents = _bfd_mmap_readonly_temporary (abfd, contents_size, + &contents_addr, + &contents_size); if (contents == NULL) goto error_return_verref; @@ -9604,8 +9632,9 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver) elf_tdata (abfd)->cverrefs = i; if (contents != elf_tdata (abfd)->dt_verneed) - free (contents); + _bfd_munmap_readonly_temporary (contents_addr, contents_size); contents = NULL; + contents_addr = NULL; } if (elf_dynverdef (abfd) != 0 || elf_tdata (abfd)->dt_verdef != NULL) @@ -9646,7 +9675,10 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver) if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0) goto error_return_verdef; - contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size); + contents_size = hdr->sh_size; + contents = _bfd_mmap_readonly_temporary (abfd, contents_size, + &contents_addr, + &contents_size); if (contents == NULL) goto error_return_verdef; @@ -9800,8 +9832,9 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver) } if (contents != elf_tdata (abfd)->dt_verdef) - free (contents); + _bfd_munmap_readonly_temporary (contents_addr, contents_size); contents = NULL; + contents_addr = NULL; } else if (default_imported_symver) { @@ -9857,7 +9890,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver) error_return: if (contents != elf_tdata (abfd)->dt_verneed && contents != elf_tdata (abfd)->dt_verdef) - free (contents); + _bfd_munmap_readonly_temporary (contents_addr, contents_size); return false; } diff --git a/bfd/elflink.c b/bfd/elflink.c index 5a6cb07b2ce..42029f29f7a 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -549,22 +549,24 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info, return false; } + char *unversioned_name = NULL; + /* We don't put any version information in the dynamic string table. */ name = h->root.root.string; p = strchr (name, ELF_VER_CHR); if (p != NULL) - /* We know that the p points into writable memory. In fact, - there are only a few symbols that have read-only names, being - those like _GLOBAL_OFFSET_TABLE_ that are created specially - by the backends. Most symbols will have names pointing into - an ELF string table read from a file, or to objalloc memory. */ - *p = 0; + { + unversioned_name = bfd_malloc (p - name + 1); + memcpy (unversioned_name, name, p - name); + unversioned_name[p - name] = 0; + name = unversioned_name; + } indx = _bfd_elf_strtab_add (dynstr, name, p != NULL); if (p != NULL) - *p = ELF_VER_CHR; + free (unversioned_name); if (indx == (size_t) -1) return false; diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index b8b2ce7ba09..c5a79cf932c 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -851,6 +851,10 @@ extern struct bfd_link_info *_bfd_get_link_info (bfd *) extern bool _bfd_link_keep_memory (struct bfd_link_info *) ATTRIBUTE_HIDDEN; +extern uintptr_t _bfd_pagesize ATTRIBUTE_HIDDEN; +extern uintptr_t _bfd_pagesize_m1 ATTRIBUTE_HIDDEN; +extern uintptr_t _bfd_minimum_mmap_size ATTRIBUTE_HIDDEN; + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else @@ -888,6 +892,19 @@ _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) return NULL; } +#ifdef USE_MMAP +extern void *_bfd_mmap_readonly_persistent + (bfd *, size_t) ATTRIBUTE_HIDDEN; +extern void *_bfd_mmap_readonly_temporary + (bfd *, size_t, void **, size_t *) ATTRIBUTE_HIDDEN; +extern void _bfd_munmap_readonly_temporary + (void *, size_t) ATTRIBUTE_HIDDEN; +#else +#define _bfd_mmap_readonly_persistent(abfd, rsize) \ + _bfd_alloc_and_read (abfd, rsize, rsize) +#define _bfd_munmap_readonly_temporary(ptr, rsize) free (ptr) +#endif + static inline void * _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) { @@ -910,3 +927,15 @@ _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) } return NULL; } + +#ifndef USE_MMAP +static inline void * +_bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr, + size_t *map_size) +{ + void *mem = _bfd_malloc_and_read (abfd, rsize, rsize); + *map_addr = mem; + *map_size = rsize; + return mem; +} +#endif diff --git a/bfd/libbfd.c b/bfd/libbfd.c index f8d148c9677..a79c814a0dc 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -1038,6 +1038,141 @@ bfd_get_bits (const void *p, int bits, bool big_p) return data; } +#ifdef USE_MMAP +/* Allocate a page to track mmapped memory and return the page and + the first entry. Return NULL if mmap fails. */ + +static struct bfd_mmapped * +bfd_allocate_mmapped_page (bfd *abfd, struct bfd_mmapped_entry **entry) +{ + struct bfd_mmapped * mmapped + = (struct bfd_mmapped *) mmap (NULL, _bfd_pagesize, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (mmapped == MAP_FAILED) + return NULL; + + mmapped->next = abfd->mmapped; + mmapped->max_entry + = ((_bfd_pagesize - offsetof (struct bfd_mmapped, entries)) + / sizeof (struct bfd_mmapped_entry)); + mmapped->next_entry = 1; + abfd->mmapped = mmapped; + *entry = mmapped->entries; + return mmapped; +} + +/* Mmap a memory region of RSIZE bytes with PROT at the current offset. + Return mmap address and size in MAP_ADDR and MAP_SIZE. Return NULL + on invalid input and MAP_FAILED for mmap failure. */ + +static void * +bfd_mmap_local (bfd *abfd, size_t rsize, int prot, void **map_addr, + size_t *map_size) +{ + if (!_bfd_constant_p (rsize)) + { + ufile_ptr filesize = bfd_get_file_size (abfd); + if (filesize != 0 && rsize > filesize) + { + bfd_set_error (bfd_error_file_truncated); + return NULL; + } + } + + void *mem; + ufile_ptr offset = bfd_tell (abfd); + mem = bfd_mmap (abfd, NULL, rsize, prot, MAP_PRIVATE, offset, + map_addr, map_size); + return mem; +} + +/* Mmap a readonly memory region of RSIZE bytes at the current offset. + Return mmap address and size in MAP_ADDR and MAP_SIZE. Return NULL + on invalid input and MAP_FAILED for mmap failure. */ + +void * +_bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr, + size_t *map_size) +{ + /* Use mmap only if section size >= the minimum mmap section size. */ + if (rsize < _bfd_minimum_mmap_size) + { + void *mem = _bfd_malloc_and_read (abfd, rsize, rsize); + /* NB: Set *MAP_ADDR to MEM and *MAP_SIZE to 0 to indicate that + _bfd_malloc_and_read is called. */ + *map_addr = mem; + *map_size = 0; + return mem; + } + + return bfd_mmap_local (abfd, rsize, PROT_READ, map_addr, map_size); +} + +/* Munmap RSIZE bytes at PTR. */ + +void +_bfd_munmap_readonly_temporary (void *ptr, size_t rsize) +{ + /* NB: Since _bfd_munmap_readonly_temporary is called like free, PTR + may be NULL. Otherwise, PTR and RSIZE must be valid. If RSIZE is + 0, _bfd_malloc_and_read is called. */ + if (ptr == NULL) + return; + if (rsize != 0) + { + if (munmap (ptr, rsize) != 0) + abort (); + } + else + free (ptr); +} + +/* Mmap a readonly memory region of RSIZE bytes at the current offset. + Return NULL on invalid input or mmap failure. */ + +void * +_bfd_mmap_readonly_persistent (bfd *abfd, size_t rsize) +{ + /* Use mmap only if section size >= the minimum mmap section size. */ + if (rsize < _bfd_minimum_mmap_size) + return _bfd_alloc_and_read (abfd, rsize, rsize); + + void *mem, *map_addr; + size_t map_size; + mem = bfd_mmap_local (abfd, rsize, PROT_READ, &map_addr, &map_size); + if (mem == NULL) + return mem; + if (mem == MAP_FAILED) + return _bfd_alloc_and_read (abfd, rsize, rsize); + + struct bfd_mmapped_entry *entry; + unsigned int next_entry; + struct bfd_mmapped *mmapped = abfd->mmapped; + if (mmapped != NULL + && (next_entry = mmapped->next_entry) < mmapped->max_entry) + { + entry = &mmapped->entries[next_entry]; + mmapped->next_entry++; + } + else + { + mmapped = bfd_allocate_mmapped_page (abfd, &entry); + if (mmapped == NULL) + { + munmap (map_addr, map_size); + return NULL; + } + } + + entry->addr = map_addr; + entry->size = map_size; + + return mem; +} +#endif + /* Default implementation */ bool @@ -1326,3 +1461,19 @@ _bfd_generic_init_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED, { return true; } + +uintptr_t _bfd_pagesize; +uintptr_t _bfd_pagesize_m1; +uintptr_t _bfd_minimum_mmap_size; + +__attribute__ ((unused, constructor)) +static void +bfd_init_pagesize (void) +{ + _bfd_pagesize = getpagesize (); + if (_bfd_pagesize == 0) + abort (); + _bfd_pagesize_m1 = _bfd_pagesize - 1; + /* The minimum section size to use mmap. */ + _bfd_minimum_mmap_size = _bfd_pagesize * 4; +} diff --git a/bfd/libbfd.h b/bfd/libbfd.h index f15b5f27db8..47f40889a95 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -857,6 +857,10 @@ extern struct bfd_link_info *_bfd_get_link_info (bfd *) extern bool _bfd_link_keep_memory (struct bfd_link_info *) ATTRIBUTE_HIDDEN; +extern uintptr_t _bfd_pagesize ATTRIBUTE_HIDDEN; +extern uintptr_t _bfd_pagesize_m1 ATTRIBUTE_HIDDEN; +extern uintptr_t _bfd_minimum_mmap_size ATTRIBUTE_HIDDEN; + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else @@ -894,6 +898,19 @@ _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) return NULL; } +#ifdef USE_MMAP +extern void *_bfd_mmap_readonly_persistent + (bfd *, size_t) ATTRIBUTE_HIDDEN; +extern void *_bfd_mmap_readonly_temporary + (bfd *, size_t, void **, size_t *) ATTRIBUTE_HIDDEN; +extern void _bfd_munmap_readonly_temporary + (void *, size_t) ATTRIBUTE_HIDDEN; +#else +#define _bfd_mmap_readonly_persistent(abfd, rsize) \ + _bfd_alloc_and_read (abfd, rsize, rsize) +#define _bfd_munmap_readonly_temporary(ptr, rsize) free (ptr) +#endif + static inline void * _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) { @@ -916,6 +933,18 @@ _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) } return NULL; } + +#ifndef USE_MMAP +static inline void * +_bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr, + size_t *map_size) +{ + void *mem = _bfd_malloc_and_read (abfd, rsize, rsize); + *map_addr = mem; + *map_size = rsize; + return mem; +} +#endif /* Extracted from libbfd.c. */ void *bfd_malloc (bfd_size_type /*size*/) ATTRIBUTE_HIDDEN; diff --git a/bfd/lynx-core.c b/bfd/lynx-core.c index 44d94ad8745..9ec5a0d2028 100644 --- a/bfd/lynx-core.c +++ b/bfd/lynx-core.c @@ -96,7 +96,7 @@ lynx_core_file_p (bfd *abfd) asection *newsect; size_t amt; - pagesize = getpagesize (); /* Serious cross-target issue here... This + pagesize = _bfd_pagesize; /* Serious cross-target issue here... This really needs to come from a system-specific header file. */ diff --git a/bfd/opncls.c b/bfd/opncls.c index c764d204831..e6337b88e18 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -163,6 +163,18 @@ _bfd_new_bfd_contained_in (bfd *obfd) static void _bfd_delete_bfd (bfd *abfd) { +#ifdef USE_MMAP + struct bfd_mmapped *mmapped, *next; + for (mmapped = abfd->mmapped; mmapped != NULL; mmapped = next) + { + struct bfd_mmapped_entry *entries = mmapped->entries; + next = mmapped->next; + for (unsigned int i = 0; i < mmapped->next_entry; i++) + munmap (entries[i].addr, entries[i].size); + munmap (mmapped, _bfd_pagesize); + } +#endif + /* Give the target _bfd_free_cached_info a chance to free memory. */ if (abfd->memory && abfd->xvec) bfd_free_cached_info (abfd); diff --git a/bfd/sysdep.h b/bfd/sysdep.h index b907bc26a09..173f5804df3 100644 --- a/bfd/sysdep.h +++ b/bfd/sysdep.h @@ -98,6 +98,10 @@ #define MAP_FAILED ((void *) -1) #endif +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + #include "filenames.h" #if !HAVE_DECL_FFS From patchwork Fri Mar 15 12:24:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 87239 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B3727385771D for ; Fri, 15 Mar 2024 12:25:05 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-oa1-x2f.google.com (mail-oa1-x2f.google.com [IPv6:2001:4860:4864:20::2f]) by sourceware.org (Postfix) with ESMTPS id 975233858C60 for ; Fri, 15 Mar 2024 12:24:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 975233858C60 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 975233858C60 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2001:4860:4864:20::2f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505470; cv=none; b=WXUuLWk5DspmiuBTJLbZyGIkkcoQJuFrPhJ9jcLvkwuD7m1AJ+tzyCCgGvZ/z5jgXaQy+90dPeOYn/e0W4+7lZuXA3Nl3P1NpexnwsUPrWkqP097mjMc00bmyz3xuVxpGN3Hz3flI0514J+eYvM9d0I0ONmKlf35BeRmsXtn60k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505470; c=relaxed/simple; bh=l6Q3TdHwdJxAKkm38LAOui+l+2+KYO3+kFam8GL0UOs=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=D/osdXhJwstB5vbtcjoWwfZkehuIaM4fvbIj0owlSxUzBL4JwEbyTpz2f1w7Z2fhzZ+vs4kPSP/fhGoAymkcIEGGCCTy/n+Gq8t43q17DM1vlBMM5AyfyGAxpDhEKQz0EiyNVQF7IEDb0yeZMrTC6ZgRuw/4e2RKUlOSAwY33kU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-oa1-x2f.google.com with SMTP id 586e51a60fabf-22002fbbd6bso928223fac.3 for ; Fri, 15 Mar 2024 05:24:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710505466; x=1711110266; 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=wZNt6MzHkf/nIouE0CVmrspfEkJvLyg7ZqhGDPbZ8Oo=; b=SsXNYNSh+d+7x/5jNT8DtNQ/8/ncrrVfOkPFsjxykZ7COOwN42vVOXOyA989lzRuO4 UAABaXSQcN78XLUjMesKAabb4bege2v+LqFYzi1F2E+oxQKqmxAt85pbHrgDUZTUZ9fz Eyb2kt8T3rXpvIPjIGDhQ1OBeSAXCVfzBIeSuKtywm6KQT4eXjI5aH5iL3rOi0phPD/D ++w0TbY3xsZ9cJYNlRPWDeZRgMB7lfYR8R8nMq0vL8Hr4o8fk/jSa3DppKoqHbRLPQpn Q7Y55Lm6l3lRvV4BIrnzD4cIzjWL2qz3emuUUMokoIealCpnajgQNfUnoX6guQBnQ1kX L5xQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710505466; x=1711110266; 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=wZNt6MzHkf/nIouE0CVmrspfEkJvLyg7ZqhGDPbZ8Oo=; b=G9auRJJm6/Kgnhwwn7NnUyuB6M03wXu35PGEEQnM2155INSMjZ6as6OcoXnJixI2EO RgiV7l5TBoW21KZNWM12RwEao6ApoSwGoaqJZhMfog96aR7Gqd2mbjsZKqNIIYeuS63V DJf6GeBz33xExmPy3Dd0COlm7vZj5mqyWQTt7R3AV+p2kBkbV6SmqXO8W7TyuLiczulM QPMsoEaWf9BK5c0XwoJpUzIp7eegod3M0nTg53fHH2b8ugwy5mCV9cClM30cBl2Bhqdw FsIPqiGnZj8NrkFR7aJ1DKp9y6omp68I+62MT6g5AAJsl738OfhFyh+JIO703vaPqrDx FsZg== X-Gm-Message-State: AOJu0Yx1ptsvpdOh5hZFn+E5fFxSaLsnt3XWmfXSsZFW9XQp7XGjnzkz hV7kBJ7efk7aN8oqes29+5DgluZZXcTTw0SSnfHDaNC9n+mR9YeK/LaOE/Bc X-Google-Smtp-Source: AGHT+IGksvi+s/5/WZz++DW7AuEdFQy2Z9XADhAKoG6yEqhSSSj/zE4l+wbOrp2Wt6/MHiuiLbyBsA== X-Received: by 2002:a05:6871:2b13:b0:222:d6a:9ae6 with SMTP id dr19-20020a0568712b1300b002220d6a9ae6mr5020012oac.47.1710505465458; Fri, 15 Mar 2024 05:24:25 -0700 (PDT) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id p6-20020aa78606000000b006e6add563acsm3262683pfn.9.2024.03.15.05.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 05:24:24 -0700 (PDT) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id 92C597403E1; Fri, 15 Mar 2024 05:24:23 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, sam@gentoo.org, amodra@gmail.com Subject: [PATCH v11 2/6] elf: Add _bfd_elf_m[un]map_section_contents Date: Fri, 15 Mar 2024 05:24:19 -0700 Message-ID: <20240315122423.1963285-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315122423.1963285-1-hjl.tools@gmail.com> References: <20240315122423.1963285-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3020.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org Add _bfd_elf_mmap_section_contents and _bfd_elf_munmap_section_contents. A backend must opt-in to use mmap. It should replace bfd_malloc_and_get_section -> _bfd_elf_mmap_section_contents free -> _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_contents): 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_contents and _bfd_elf_munmap_section_contents on section contents. * elf-sframe.c (_bfd_elf_parse_sframe): Likewise. * elf.c (_bfd_elf_make_section_from_shdr): Replace bfd_malloc_and_get_section and free with _bfd_elf_mmap_section_contents and _bfd_elf_munmap_section_contents on section contents. (_bfd_elf_print_private_bfd_data): Likewise. (_bfd_elf_mmap_section_contents): 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_contents 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_contents 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 | 87 +++++++++++++++++++++++++++++++++++++++++++--- 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 | 8 ++--- bfd/elfxx-x86.h | 1 + bfd/libbfd.c | 59 +++++++++++++++++++++++++++++-- bfd/opncls.c | 9 +++++ bfd/section.c | 9 +++-- 16 files changed, 212 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..e7c2cd19bed 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_contents + 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_contents + (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..902d7c16334 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_contents (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..a4e3143e9d2 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_contents (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 c80fff47b45..557c1ac5f4a 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1123,12 +1123,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_contents (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) @@ -1708,7 +1708,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_contents (abfd, s, &dynbuf)) goto error_return; elfsec = _bfd_elf_section_from_bfd_section (abfd, s); @@ -1830,7 +1830,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; } @@ -1887,7 +1887,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; } @@ -14392,3 +14392,80 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) return result; } + +/* Mmap in section contents. */ + +bool +_bfd_elf_mmap_section_contents (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) + { + /* _bfd_elf_mmap_section_contents may return the previously + mapped section contents. Munmap the section contents only + if they haven't been cached. */ + if (elf_section_data (sec)->this_hdr.contents == contents) + return; + + /* When _bfd_elf_mmap_section_contents returns CONTENTS as + malloced, 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..0f963c373be 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_contents (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..2e3f86840e5 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_contents (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_contents (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..39dfe0ba234 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_contents (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..216c124b207 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_contents (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_contents (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..b6904273c42 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -1566,9 +1566,9 @@ 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_contents (sec->owner, + sec, + &contents)) info->callbacks->einfo /* xgettext:c-format */ (_("%F%P: %pB: failed to allocate memory for section `%pA'\n"), @@ -3789,7 +3789,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 a79c814a0dc..e5147a29d69 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" @@ -1196,6 +1197,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-NULL 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 @@ -1208,8 +1222,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 iovec not supporting mmap. */ + if (location != MAP_FAILED) + { + 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 e6337b88e18..5efec37175e 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -164,6 +164,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); } From patchwork Fri Mar 15 12:24:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 87240 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 17321385771D for ; Fri, 15 Mar 2024 12:25:08 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by sourceware.org (Postfix) with ESMTPS id 4631038582B1 for ; Fri, 15 Mar 2024 12:24:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4631038582B1 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 4631038582B1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505470; cv=none; b=FDw3qOWJys9h5bLHUqyz0JyZnGv5lHGKYsQZF0jgI4VuqiJDPe2xny9JPvLQNTgi5vl2fdxPGypkIlMjMNCtYwh/YdfE+LSiMDNPHRYfQrWm4iZhWjNCUt4FMkEgXghsRHuwmgaU2mPXo/g5FZc1FiPz+3jZQDOCXHCaIgGSlhc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505470; c=relaxed/simple; bh=cUif8EDRcOt0wrXByfEpDvZO73Rsmjt4BXHWCubQxwQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=eBycusMvIxpDAp5xPzpTSxj6ufU2ZeQ6nmioxnBSYYT2LLr6gJMP6bzQdzEl8PipjmNAaufmle0TvFOxBq2VFkup7g4oXpwCn4sdftF62ml2ihXE7rCNdu6qREC9+TK/LHX/ednmC+AQm19lPw8YuUchdZAUn8t93L88ZgtdrWQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-1dedb92e540so12205315ad.0 for ; Fri, 15 Mar 2024 05:24:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710505467; x=1711110267; 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=VNTyCjM0V5mSzAAU47ebhXmIyUQPdSaBs8ItU6F51fU=; b=hoiVQJ8gz7a0YSA7rB1HwYjUZbcN2t045FCh9WNRvbw7+6qfKDPJecxluFLZ163g0V wUl+9LXIRm5wcGYraKly1FEeUk1XbzGqYmxiyTaAkisNzHgHzv3yMJc2gKep5jWvp+yu A0w92S+VZbK3QdbUxwb5Cqsn9TW3JUwr9k/gsBINOSgOtHmg69Ic6xXBQBM3IB57C4DB LGr2TxpM0IH3dKgf17LqkILjP7/gUFL2cSZFimMQ1wQ+rpvDkWKs+3nJZZX3X6K/m6Ya bYZRTVySZr2CN7KA7b68BDlDg0Z5AJfzY9wcV0P9+G9jLmEuE2s9UNco0yiVYgFnczfo cPSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710505467; x=1711110267; 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=VNTyCjM0V5mSzAAU47ebhXmIyUQPdSaBs8ItU6F51fU=; b=FPeG42le/U4vapx+382C9xRGZaP9qSKz9Lv7Q1IRwaZupwV1d5hla0tsSRKDH9xRyZ /ojw92TIu6uyWX0lJr++bgwvzZb59MC5nERNT8Fnn/C1vqud2kTpCEQ0mJMc1UmNQl8I 53bDQQFa6nF/R9ycv12PxHqrxAGoclEUWq9ftxnsBvjxf6SxPTZyrZoqz2Qwd0T6OeQK qGtW16OuFIVWDtgp1OO94LhVbkIyRlp5kk+zRM2M6Mnmr2rJarC7Qne94dr+08nDRpoe 27in4CPLSjqMHFNCkxRmpMVD+ct3c/FsgPayzXpxqwVviTBEPsaf81Q3rVXkEDi2iXi9 6wcA== X-Gm-Message-State: AOJu0YweBfcB7qTU2zr7NZ9Ca8YX3clzSdyCPVB4H6Tz/xx1elbM6TKt gv+UFM6APRJ9Pt/E9yZgAyxczCmE/A5TbXB7KxnSAV97lq1d6Pr7 X-Google-Smtp-Source: AGHT+IHS152MHgVM7XPFJXmMg+bfimWpbHwq4dbSMMII8Xjk66K4TODuANcxR+DESI3c7qhmL4J54Q== X-Received: by 2002:a17:903:234b:b0:1de:fab2:98eb with SMTP id c11-20020a170903234b00b001defab298ebmr670111plh.5.1710505467203; Fri, 15 Mar 2024 05:24:27 -0700 (PDT) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id le13-20020a170902fb0d00b001dcc2951c02sm3674985plb.286.2024.03.15.05.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 05:24:24 -0700 (PDT) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id 9F5787404C9; Fri, 15 Mar 2024 05:24:23 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, sam@gentoo.org, amodra@gmail.com Subject: [PATCH v11 3/6] elf: Use mmap to map in symbol and relocation tables Date: Fri, 15 Mar 2024 05:24:20 -0700 Message-ID: <20240315122423.1963285-4-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315122423.1963285-1-hjl.tools@gmail.com> References: <20240315122423.1963285-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3020.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org Add _bfd_mmap_read_temporary to mmap in symbol tables and relocations whose sizes >= 4 * page size. For the final link, allocate an external relocation buffer of 4 * page size to avoid using mmap and munmap on smaller relocation sections. Since _bfd_mmap_read_temporary allocates buffer as needed, its callers don't need to. When mmap is used to map in all ELF sections, data to link the 3.5GB clang executable in LLVM 17 debug build on Linux/x86-64 with 32GB RAM is: stdio mmap improvement user 84.79 85.27 -0.5% system 10.95 9.09 17% total 97.91 94.90 3% page faults 4837944 4033778 17% and data to link the 275M cc1plus executable in GCC 14 stage 1 build is: user 5.31 5.33 -0.4% system 0.86 0.76 12% total 6.19 6.13 1% page faults 361273 322491 11% * elf.c (bfd_elf_get_elf_syms): Don't allocate buffer for external symbol table. Replace bfd_read with _bfd_mmap_read_temporary. * elflink.c (elf_link_read_relocs_from_section): Add 2 arguments to return mmap memory address and size. (_bfd_elf_link_info_read_relocs): Don't allocate buffer for external relocation information. Replace bfd_read with _bfd_mmap_read_temporary. (bfd_elf_final_link): Cache external relocations up to _bfd_minimum_mmap_size bytes when mmap is used. * libbfd.c (_bfd_mmap_read_temporary): New. * libbfd-in.h (_bfd_mmap_read_temporary): Likewise. * libbfd.h: Regenerated. --- bfd/elf.c | 31 +++++++++++++---------------- bfd/elflink.c | 50 +++++++++++++++++++++++++---------------------- bfd/libbfd-in.h | 3 +++ bfd/libbfd.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ bfd/libbfd.h | 3 +++ 5 files changed, 98 insertions(+), 41 deletions(-) diff --git a/bfd/elf.c b/bfd/elf.c index 557c1ac5f4a..cb47c499704 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -460,19 +460,16 @@ bfd_elf_get_elf_syms (bfd *ibfd, goto out; } pos = symtab_hdr->sh_offset + symoffset * extsym_size; - if (extsym_buf == NULL) - { - alloc_ext = bfd_malloc (amt); - extsym_buf = alloc_ext; - } - if (extsym_buf == NULL - || bfd_seek (ibfd, pos, SEEK_SET) != 0 - || bfd_read (extsym_buf, amt, ibfd) != amt) + size_t alloc_ext_size = amt; + if (bfd_seek (ibfd, pos, SEEK_SET) != 0 + || !_bfd_mmap_read_temporary (&extsym_buf, &alloc_ext_size, + &alloc_ext, ibfd, false)) { intsym_buf = NULL; goto out; } + size_t alloc_extshndx_size = 0; if (shndx_hdr == NULL || shndx_hdr->sh_size == 0) extshndx_buf = NULL; else @@ -483,15 +480,13 @@ bfd_elf_get_elf_syms (bfd *ibfd, intsym_buf = NULL; goto out; } + alloc_extshndx_size = amt; pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx); - if (extshndx_buf == NULL) - { - alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - extshndx_buf = alloc_extshndx; - } - if (extshndx_buf == NULL - || bfd_seek (ibfd, pos, SEEK_SET) != 0 - || bfd_read (extshndx_buf, amt, ibfd) != amt) + if (bfd_seek (ibfd, pos, SEEK_SET) != 0 + || !_bfd_mmap_read_temporary ((void **) &extshndx_buf, + &alloc_extshndx_size, + (void **) &alloc_extshndx, + ibfd, false)) { intsym_buf = NULL; goto out; @@ -530,8 +525,8 @@ bfd_elf_get_elf_syms (bfd *ibfd, } out: - free (alloc_ext); - free (alloc_extshndx); + _bfd_munmap_readonly_temporary (alloc_ext, alloc_ext_size); + _bfd_munmap_readonly_temporary (alloc_extshndx, alloc_extshndx_size); return intsym_buf; } diff --git a/bfd/elflink.c b/bfd/elflink.c index 216c124b207..9162df60bfa 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2644,8 +2644,11 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) may be either a REL or a RELA section. The relocations are translated into RELA relocations and stored in INTERNAL_RELOCS, which should have already been allocated to contain enough space. - The EXTERNAL_RELOCS are a buffer where the external form of the - relocations should be stored. + The *EXTERNAL_RELOCS_P are a buffer where the external form of the + relocations should be stored. If *EXTERNAL_RELOCS_ADDR is NULL, + *EXTERNAL_RELOCS_ADDR and *EXTERNAL_RELOCS_SIZE returns the mmap + memory address and size. Otherwise, *EXTERNAL_RELOCS_ADDR is + unchanged and *EXTERNAL_RELOCS_SIZE returns 0. Returns FALSE if something goes wrong. */ @@ -2653,7 +2656,8 @@ static bool elf_link_read_relocs_from_section (bfd *abfd, asection *sec, Elf_Internal_Shdr *shdr, - void *external_relocs, + void **external_relocs_addr, + size_t *external_relocs_size, Elf_Internal_Rela *internal_relocs) { const struct elf_backend_data *bed; @@ -2663,13 +2667,17 @@ elf_link_read_relocs_from_section (bfd *abfd, Elf_Internal_Rela *irela; Elf_Internal_Shdr *symtab_hdr; size_t nsyms; + void *external_relocs = *external_relocs_addr; /* Position ourselves at the start of the section. */ if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0) return false; /* Read the relocations. */ - if (bfd_read (external_relocs, shdr->sh_size, abfd) != shdr->sh_size) + *external_relocs_size = shdr->sh_size; + if (!_bfd_mmap_read_temporary (&external_relocs, + external_relocs_size, + external_relocs_addr, abfd, true)) return false; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; @@ -2754,6 +2762,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, bool keep_memory) { void *alloc1 = NULL; + size_t alloc1_size; Elf_Internal_Rela *alloc2 = NULL; const struct elf_backend_data *bed = get_elf_backend_data (abfd); struct bfd_elf_section_data *esdo = elf_section_data (o); @@ -2782,26 +2791,12 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, goto error_return; } - if (external_relocs == NULL) - { - bfd_size_type size = 0; - - if (esdo->rel.hdr) - size += esdo->rel.hdr->sh_size; - if (esdo->rela.hdr) - size += esdo->rela.hdr->sh_size; - - alloc1 = bfd_malloc (size); - if (alloc1 == NULL) - goto error_return; - external_relocs = alloc1; - } - + alloc1 = external_relocs; internal_rela_relocs = internal_relocs; if (esdo->rel.hdr) { if (!elf_link_read_relocs_from_section (abfd, o, esdo->rel.hdr, - external_relocs, + &alloc1, &alloc1_size, internal_relocs)) goto error_return; external_relocs = (((bfd_byte *) external_relocs) @@ -2812,7 +2807,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, if (esdo->rela.hdr && (!elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr, - external_relocs, + &alloc1, &alloc1_size, internal_rela_relocs))) goto error_return; @@ -2820,7 +2815,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, if (keep_memory) esdo->relocs = internal_relocs; - free (alloc1); + _bfd_munmap_readonly_temporary (alloc1, alloc1_size); /* Don't free alloc2, since if it was allocated we are passing it back (under the name of internal_relocs). */ @@ -2828,7 +2823,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd, return internal_relocs; error_return: - free (alloc1); + _bfd_munmap_readonly_temporary (alloc1, alloc1_size); if (alloc2 != NULL) { if (keep_memory) @@ -12444,7 +12439,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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. */ + max_external_reloc_size = _bfd_minimum_mmap_size; +#else max_external_reloc_size = 0; +#endif max_internal_reloc_count = 0; max_sym_count = 0; max_sym_shndx_count = 0; @@ -12533,8 +12535,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (esdi->rela.hdr != NULL) ext_size += esdi->rela.hdr->sh_size; +#ifndef USE_MMAP if (ext_size > max_external_reloc_size) max_external_reloc_size = ext_size; +#endif if (sec->reloc_count > max_internal_reloc_count) max_internal_reloc_count = sec->reloc_count; } diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index c5a79cf932c..889b221a950 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -905,6 +905,9 @@ extern void _bfd_munmap_readonly_temporary #define _bfd_munmap_readonly_temporary(ptr, rsize) free (ptr) #endif +extern bool _bfd_mmap_read_temporary + (void **, size_t *, void **, bfd *, bool) ATTRIBUTE_HIDDEN; + static inline void * _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) { diff --git a/bfd/libbfd.c b/bfd/libbfd.c index e5147a29d69..869f0ed5c66 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -1174,6 +1174,58 @@ _bfd_mmap_readonly_persistent (bfd *abfd, size_t rsize) } #endif +/* Attempt to read *SIZE_P bytes from ABFD's iostream to *DATA_P. + Return true if the full the amount has been read. If *DATA_P is + NULL, mmap should be used, return the memory address at the + current offset in *DATA_P as well as return mmap address and size + in *MMAP_BASE and *SIZE_P. Otherwise, return NULL in *MMAP_BASE + and 0 in *SIZE_P. If FINAL_LINK is true, this is called from + elf_link_read_relocs_from_section. */ + +bool +_bfd_mmap_read_temporary (void **data_p, size_t *size_p, + void **mmap_base, bfd *abfd, + bool final_link ATTRIBUTE_UNUSED) +{ + void *data = *data_p; + size_t size = *size_p; + +#ifdef USE_MMAP + /* NB: When FINAL_LINK is true, the size of the preallocated buffer + is _bfd_minimum_mmap_size and use mmap if the data size >= + _bfd_minimum_mmap_size. Otherwise, use mmap if ABFD isn't an IR + input or the data size >= _bfd_minimum_mmap_size. */ + bool use_mmmap; + bool mmap_size = size >= _bfd_minimum_mmap_size; + if (final_link) + use_mmmap = mmap_size; + else + use_mmmap = (mmap_size + && data == NULL + && (abfd->flags & BFD_PLUGIN) == 0); + if (use_mmmap) + { + data = _bfd_mmap_readonly_temporary (abfd, size, mmap_base, + size_p); + if (data == NULL || data == MAP_FAILED) + abort (); + *data_p = data; + return true; + } +#endif + + if (data == NULL) + { + data = bfd_malloc (size); + if (data == NULL) + return false; + *data_p = data; + } + *mmap_base = NULL; + *size_p = 0; + return bfd_read (data, size, abfd) == size; +} + /* Default implementation */ bool diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 47f40889a95..876c1f223c7 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -911,6 +911,9 @@ extern void _bfd_munmap_readonly_temporary #define _bfd_munmap_readonly_temporary(ptr, rsize) free (ptr) #endif +extern bool _bfd_mmap_read_temporary + (void **, size_t *, void **, bfd *, bool) ATTRIBUTE_HIDDEN; + static inline void * _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize) { From patchwork Fri Mar 15 12:24:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 87243 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 060C83857013 for ; Fri, 15 Mar 2024 12:26:20 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id AF1543858416 for ; Fri, 15 Mar 2024 12:24:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AF1543858416 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 AF1543858416 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::635 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505473; cv=none; b=VBKQnBHuq+Ih0N3MkAi0YfMtiHkKifPh3ABg05lvhh1lu/UqU0SHsOjDEZSlpeNBWPn/73uhqvrCSDxPOqxid3v5Y+Ez+CIWF+ecD5FIpjKCQoN08ofe5K+Gc7C/mG4nx9Lbu+bNDaoCbVrC99ATZPem+nbBbz9fwy9xYCTIdEs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505473; c=relaxed/simple; bh=UGYdpfo91LFO3Xw1UH2k1Ncn8vEigZGI7lZZNctGAPc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=samq/6sWFiWzwMNEjf6loqT0CkFplqTRYbjXGi+B9oxyovBSbxJ+BlgRkMUZXphAzdyu4dnGWEd2bCyRRwebgw7+iYsdvc+TKnS7dTl8NVq5/9RoJICKGWrCnsn0/urIt39vRVdFT7RX4ju08cTbMTfxDCFMHCObRZIF29Ie79k= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1dca3951ad9so14582975ad.3 for ; Fri, 15 Mar 2024 05:24:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710505465; x=1711110265; 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=jYg/paNegawZNW6w5LmDcI67brT6zIfhOxiHJZbT5ss=; b=IFJuBdTOThDnsVHIyxjum33OBpnLA9ZIAHSginjj4i8IhzZ4v78mwA5+u/UDlH9OU5 RanD8FDMy5vF1xXf37v1qsT9Qr2wvEA12fWBmpQ8G1Rriyp2XVjLMLdK2MOWOuM6vsOT pxx5ncL3Qs4vaG4GF6J35U7E8WIAtNsdH2miDk89BeT+S4p2GTWOSDGQGBFT31qmT3ta xE1btRpcY7yUrAlzKjAhK+N8Zj4/BGlDF5ItgnAIyyyPi6Hn3iU+Py2IrQ7H5y0Nx/PB d5dV7IfHBfkwSOUOHHmrSoD2TK/4cSbkGl+zRZ14Y5mnWlHux6EviPCVhZEF5KlW4ecF HolQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710505465; x=1711110265; 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=jYg/paNegawZNW6w5LmDcI67brT6zIfhOxiHJZbT5ss=; b=AENbjPTprDCRiA5P8S3vaoMYXLfKiGgOc5KHLvxCEncfV0gMmIfSoh11YWl0uHnBwM /RcXUF9uWfcMyicxUtT9bZ5DZbEb0l/0rB4EFO5UcxuVNkPe2nepJJ5a7qblJIDCxhRI g2evJjScjzdqlvwTeb9liOWkWj3TdZ+i6mNTwLYeYdxf0wumi0PoRoCGK6UaU173AlDy 0+LrSZyDGkdlUlbTE/JhmY/lumy+5IMoUjvHCZNsZ9zDO/ZJIXQ7cqo4+k6Ed/2rXPDp 4+PDQV44fG2IXxXeaB7NDp9b1IeWI2mUgTSrUTmFcE7QCFGKisYl+eWPU2xQEO1P4/Op bB/w== X-Gm-Message-State: AOJu0Yy1CVmQHJ75V4zIrV7MPUj/mL1io3EZOmCm+Ycu3SuDEiKfPplZ q9H761PKT9jRlVEZ7S9AFNFZRwliIp7SlaLQLptqxTZndvbgT6oh X-Google-Smtp-Source: AGHT+IEJM0tY6OxFu6KNmd9T0kKKnS9/sjnPZSjykZcHAiqP1PxP9sH53hxQeUNGoTlIW76rbN0zhg== X-Received: by 2002:a17:902:7c90:b0:1de:ea06:629f with SMTP id y16-20020a1709027c9000b001deea06629fmr2357633pll.51.1710505465599; Fri, 15 Mar 2024 05:24:25 -0700 (PDT) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id w15-20020a1709026f0f00b001dd8ee1d7dfsm3739192plk.126.2024.03.15.05.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 05:24:24 -0700 (PDT) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id AA60574066D; Fri, 15 Mar 2024 05:24:23 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, sam@gentoo.org, amodra@gmail.com Subject: [PATCH v11 4/6] elf: Don't cache symbol nor relocation tables with mmap Date: Fri, 15 Mar 2024 05:24:21 -0700 Message-ID: <20240315122423.1963285-5-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315122423.1963285-1-hjl.tools@gmail.com> References: <20240315122423.1963285-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3020.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org During a "-j 8" LLVM 17 debug build on a machine with 32GB RAM and 16GB swap, ld was killed by kernel because of out of memory: [79437.949336] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/session-9.scope,task=ld,pid=797431,uid=1000 [79437.949349] Out of memory: Killed process 797431 (ld) total-vm:9219600kB, anon-rss:6558156kB, file-rss:1792kB, shmem-rss:0kB, UID:1000 pgtables:17552kB oom_score_adj:0 Don't cache symbol nor relocation tables if they are mapped in. Data to link the 3.5GB clang executable in LLVM 17 debug build on Linux/x86-64 with 32GB RAM is: stdio mmap improvement user 86.73 87.02 -0.3% system 9.55 9.21 3.6% total 100.40 97.66 0.7% maximum set(GB) 17.34 13.14 24% page faults 4047667 3042877 25% and data to link the 275M cc1plus executable in GCC 14 stage 1 build is: user 5.41 5.44 -0.5% system 0.80 0.76 5% total 6.25 6.26 -0.2% maximum set(MB) 1323 968 27% page faults 323451 236371 27% These improve the overall system performance for parallel build by reducing memory usage and page faults. Also rename _bfd_link_keep_memory to _bfd_elf_link_keep_memory. Since the --no-keep-memory linker option causes: https://sourceware.org/bugzilla/show_bug.cgi?id=31458 this is opt-in by each backend. bfd/ * elf-bfd.h (_bfd_elf_link_keep_memory): New. * elf32-i386.c (elf_i386_scan_relocs): Replace _bfd_link_keep_memory with _bfd_elf_link_keep_memory. * elf64-x86-64.c (elf_x86_64_scan_relocs): Likewise. * elflink.c (_bfd_elf_link_iterate_on_relocs): Likewise. (elf_link_add_object_symbols): Likewise. (init_reloc_cookie): Likewise. (init_reloc_cookie_rels): Likewise. (_bfd_elf_link_keep_memory): New. * libbfd-in.h (_bfd_link_keep_memory): Removed. * linker.c (_bfd_link_keep_memory): Likewise. * libbfd.h: Regenerated. --- bfd/elf-bfd.h | 3 ++ bfd/elf32-i386.c | 2 +- bfd/elf64-x86-64.c | 2 +- bfd/elflink.c | 69 ++++++++++++++++++++++++++++++++++++++-------- bfd/libbfd-in.h | 3 -- bfd/libbfd.h | 3 -- bfd/linker.c | 35 ----------------------- 7 files changed, 62 insertions(+), 55 deletions(-) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index e7c2cd19bed..b9ec590cd4e 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -3144,6 +3144,9 @@ extern bool _bfd_elf_mmap_section_contents extern void _bfd_elf_munmap_section_contents (asection *, void *); +extern bool _bfd_elf_link_keep_memory + (struct bfd_link_info *); + /* Large common section. */ extern asection _bfd_elf_large_com_section; diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 0f963c373be..d1bd11094de 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1932,7 +1932,7 @@ elf_i386_scan_relocs (bfd *abfd, if (elf_section_data (sec)->this_hdr.contents != contents) { - if (!converted && !_bfd_link_keep_memory (info)) + if (!converted && !_bfd_elf_link_keep_memory (info)) _bfd_elf_munmap_section_contents (sec, contents); else { diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 2e3f86840e5..5e1fad069d1 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2590,7 +2590,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)) + if (!converted && !_bfd_elf_link_keep_memory (info)) _bfd_elf_munmap_section_contents (sec, contents); else { diff --git a/bfd/elflink.c b/bfd/elflink.c index 9162df60bfa..877bb9874ae 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4182,10 +4182,9 @@ _bfd_elf_link_iterate_on_relocs || bfd_is_abs_section (o->output_section)) continue; - internal_relocs = _bfd_elf_link_info_read_relocs (abfd, info, - o, NULL, - NULL, - _bfd_link_keep_memory (info)); + internal_relocs = _bfd_elf_link_info_read_relocs + (abfd, info, o, NULL, NULL, + _bfd_elf_link_keep_memory (info)); if (internal_relocs == NULL) return false; @@ -5551,10 +5550,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) && (s->flags & SEC_DEBUGGING) != 0)) continue; - internal_relocs = _bfd_elf_link_info_read_relocs (abfd, info, - s, NULL, - NULL, - _bfd_link_keep_memory (info)); + internal_relocs = _bfd_elf_link_info_read_relocs + (abfd, info, s, NULL, NULL, + _bfd_elf_link_keep_memory (info)); if (internal_relocs == NULL) goto error_free_vers; @@ -13614,7 +13612,7 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie, info->callbacks->einfo (_("%P%X: can not read symbols: %E\n")); return false; } - if (_bfd_link_keep_memory (info) ) + if (_bfd_elf_link_keep_memory (info) ) { symtab_hdr->contents = (bfd_byte *) cookie->locsyms; info->cache_size += (cookie->locsymcount @@ -13651,9 +13649,9 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie, } else { - cookie->rels = _bfd_elf_link_info_read_relocs (abfd, info, sec, - NULL, NULL, - _bfd_link_keep_memory (info)); + cookie->rels = _bfd_elf_link_info_read_relocs + (abfd, info, sec, NULL, NULL, + _bfd_elf_link_keep_memory (info)); if (cookie->rels == NULL) return false; cookie->rel = cookie->rels; @@ -15583,3 +15581,50 @@ _bfd_elf_add_dynamic_tags (bfd *output_bfd, struct bfd_link_info *info, return true; } + +/* Return false if linker should avoid caching relocation information + and symbol tables of input files in memory. */ + +bool +_bfd_elf_link_keep_memory (struct bfd_link_info *info) +{ +#ifdef USE_MMAP + /* Don't cache symbol nor relocation tables if they are mapped in. + NB: Since the --no-keep-memory linker option causes: + + https://sourceware.org/bugzilla/show_bug.cgi?id=31458 + + this is opt-in by each backend. */ + const struct elf_backend_data *bed + = get_elf_backend_data (info->output_bfd); + if (bed->use_mmap) + return false; +#endif + bfd *abfd; + bfd_size_type size; + + if (!info->keep_memory) + return false; + + if (info->max_cache_size == (bfd_size_type) -1) + return true; + + abfd = info->input_bfds; + size = info->cache_size; + do + { + if (size >= info->max_cache_size) + { + /* Over the limit. Reduce the memory usage. */ + info->keep_memory = false; + return false; + } + if (!abfd) + break; + size += abfd->alloc_size; + abfd = abfd->link.next; + } + while (1); + + return true; +} diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 889b221a950..7bfc58f12d8 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -848,9 +848,6 @@ extern bfd_byte * _bfd_write_unsigned_leb128 extern struct bfd_link_info *_bfd_get_link_info (bfd *) ATTRIBUTE_HIDDEN; -extern bool _bfd_link_keep_memory (struct bfd_link_info *) - ATTRIBUTE_HIDDEN; - extern uintptr_t _bfd_pagesize ATTRIBUTE_HIDDEN; extern uintptr_t _bfd_pagesize_m1 ATTRIBUTE_HIDDEN; extern uintptr_t _bfd_minimum_mmap_size ATTRIBUTE_HIDDEN; diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 876c1f223c7..36fe6c0ebd0 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -854,9 +854,6 @@ extern bfd_byte * _bfd_write_unsigned_leb128 extern struct bfd_link_info *_bfd_get_link_info (bfd *) ATTRIBUTE_HIDDEN; -extern bool _bfd_link_keep_memory (struct bfd_link_info *) - ATTRIBUTE_HIDDEN; - extern uintptr_t _bfd_pagesize ATTRIBUTE_HIDDEN; extern uintptr_t _bfd_pagesize_m1 ATTRIBUTE_HIDDEN; extern uintptr_t _bfd_minimum_mmap_size ATTRIBUTE_HIDDEN; diff --git a/bfd/linker.c b/bfd/linker.c index 36cca9624c2..eb42a78b622 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -3556,38 +3556,3 @@ _bfd_nolink_bfd_define_start_stop (struct bfd_link_info *info ATTRIBUTE_UNUSED, { return (struct bfd_link_hash_entry *) _bfd_ptr_bfd_null_error (sec->owner); } - -/* Return false if linker should avoid caching relocation infomation - and symbol tables of input files in memory. */ - -bool -_bfd_link_keep_memory (struct bfd_link_info * info) -{ - bfd *abfd; - bfd_size_type size; - - if (!info->keep_memory) - return false; - - if (info->max_cache_size == (bfd_size_type) -1) - return true; - - abfd = info->input_bfds; - size = info->cache_size; - do - { - if (size >= info->max_cache_size) - { - /* Over the limit. Reduce the memory usage. */ - info->keep_memory = false; - return false; - } - if (!abfd) - break; - size += abfd->alloc_size; - abfd = abfd->link.next; - } - while (1); - - return true; -} From patchwork Fri Mar 15 12:24:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 87242 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3F772385772A for ; Fri, 15 Mar 2024 12:26:08 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by sourceware.org (Postfix) with ESMTPS id C17643857B86 for ; Fri, 15 Mar 2024 12:24:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C17643857B86 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 C17643857B86 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::430 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505478; cv=none; b=WV/xok1JmIQBDg+ReLWf24eE6WILtjmwto8Dcm26C+kr+R74hoJpb/s2dau2E7cSjJVMjFwigF8erfoPouD4AB1ut6+fECEv6bYNA77IEUqoKFyOUookl5uckBeAfnNfh5ix+7Sr97tvvd8L2Wpl1TwTBJ7lzUEglAkH9kNp1Qw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505478; c=relaxed/simple; bh=xqryLhe3v0SEjinMY9QPWfPXAg4w6jxneAOnUMdzKAU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=GOtjY8S3m5hFDhNCv18TWOCIqKq4akSmFbcympLJcyTtg0GoyrlNbqyGdxqww5mMbmF1yZotDkgp3Tjo5zNvbjq8LPsyjqa5Va8WmGcMLV28kyK6w5KYrRin2JS4wX7jk7ihOUwxl7VJZdtICsN3EjQEISV0n7s8o4KwKCEtRAQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-6e6082eab17so1882094b3a.1 for ; Fri, 15 Mar 2024 05:24:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710505469; x=1711110269; 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=+THdn5+KmqzjyCs5p7nilHVu1QhKx7HopYfDHPbwkHE=; b=XawiJcXHJb8eL/jL+eet/cchO+H5avikIerv0sUA1dPj09p5054UAv1n8XSdW26Z6h 5pOJ4Y6W8KF88atxeSZgx6gWh3OY6/u0vJmPrbgdfbF/fKUP4BxLK61nkFiLsBTkxLu2 usA16l7NWH9gzgxnCrXQnc3H8/OjT/SUpN27+nSYVanxuf2P2f/66eIC8kt1aR5Hbf2D OQU3ThJ7AZHDBtd9ATHTGjhtaosm05U0vnqswoHBid6PXpBXAGHY9HK+Ta2L0qPs2bGk RmHyz6bN8wP4jWMsmCnbPvCiT7k2Icux6ctsmW2VeFnbWHwytFbSzrOKjnf/1lffLQQO +4Bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710505469; x=1711110269; 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=+THdn5+KmqzjyCs5p7nilHVu1QhKx7HopYfDHPbwkHE=; b=UkbL8zw2I+H3ww6q0SoM3khITuOrbU+nXUsUAsKTo7CGJfoHa/AXHFlco1VbiYyoU5 WCdrtLHlmmi1UP3bY/5/kw4ocCq2f4sMCT5PggmogqxOt/b1VV+Yjn50o3vxd+j70c++ AGMfotZqys5AY6fvwrAywM91QAHM1SrzAmJeIEGPQd30AeVmpNHiI+wD74xcEyjgf4RB /XyL2Q8btpI5h/W0XDVgCJjjK9G8Uer/Hbf7VgPudL07QLUHC6KOKKxT6pYVrHPYIThz Igy2n9XioIXawcnlfTCnqd9wzFaAuXU/+bbAoJtXVT7d3hH6/+K78OemfW6KDeuNHEmH YKaQ== X-Gm-Message-State: AOJu0YzPftZJ/q0Ek1IScp9utJQLil13UkqPR3+UPVT0z9szBug34WGH UwC4JvCiJtBm0UhExhpfkI+BNiwuPXlnlKWpx6tDjwxkY7uvt/b0 X-Google-Smtp-Source: AGHT+IEvriMUDS1lHDv/GGNTuHJXCnz+TwDBsIucv88e6yoyMpiSTI5m949o4a7Qlwqe3W+GXhYTRQ== X-Received: by 2002:a05:6a20:4d92:b0:1a3:3547:cc8d with SMTP id gj18-20020a056a204d9200b001a33547cc8dmr3612571pzb.30.1710505468704; Fri, 15 Mar 2024 05:24:28 -0700 (PDT) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id q6-20020a17090311c600b001d9a91af8a4sm3683836plh.28.2024.03.15.05.24.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 05:24:27 -0700 (PDT) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id B59B674071C; Fri, 15 Mar 2024 05:24:23 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, sam@gentoo.org, amodra@gmail.com Subject: [PATCH v11 5/6] elf: Always keep symbol table and relocation info for eh_frame Date: Fri, 15 Mar 2024 05:24:22 -0700 Message-ID: <20240315122423.1963285-6-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315122423.1963285-1-hjl.tools@gmail.com> References: <20240315122423.1963285-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3020.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org When --no-keep-memory is used, the symbol table and relocation info for eh_frame are freed after they are retrieved for each text section in the input object. If an input object has many text sections, the same data is retrieved and freed many times which can take a very long time. Update _bfd_elf_gc_mark to keep the symbol table and relocation info for eh_frame to avoid it. Data to link the 3.5GB clang executable in LLVM 17 debug build on Linux/x86-64 with 32GB RAM is: before after improvement user 86.31 86.44 -0.2% system 8.77 8.63 1.6% total 95.58 96.81 -1.3% maximum set(GB) 13.1 13.1 0% page faults 3024752 3028699 -1.3% and data to link the 275M cc1plus executable in GCC 14 stage 1 build is: user 5.49 5.46 -0.5% system 0.73 0.73 0% total 6.26 6.25 0.3% maximum set(MB) 964 964 0% page faults 235173 235796 -0.3% The memory usage impact is minimum and the link time of the Rust binary in https://sourceware.org/bugzilla/show_bug.cgi?id=31466 is reduced from 500+ seconds to 1.44 seconds, a 300x speedup. PR ld/31466 * elflink.c (init_reloc_cookie): Add a bool argument, keep_memory, for keeping memory. Always keep memory if keep_memory is true. (init_reloc_cookie_rels): Likewise (init_reloc_cookie_for_section): Add a bool argument for keeping memory and pass it to init_reloc_cookie and init_reloc_cookie_rels. (_bfd_elf_gc_mark_reloc): Pass false to _bfd_elf_gc_mark. (_bfd_elf_gc_mark): Pass true to init_reloc_cookie_for_section for the eh_frame section. Pass false to init_reloc_cookie_for_section for other sections. (_bfd_elf_gc_mark_extra_sections): Add Add a bool argument for keeping memory and pass it to _bfd_elf_gc_mark. (bfd_elf_parse_eh_frame_entries): Pass false to init_reloc_cookie and init_reloc_cookie_rels. (bfd_elf_gc_sections): Pass false to init_reloc_cookie_for_section and _bfd_elf_gc_mark. (bfd_elf_discard_info): Pass false to init_reloc_cookie_for_section and init_reloc_cookie. --- bfd/elflink.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/bfd/elflink.c b/bfd/elflink.c index 877bb9874ae..4eb6ce5b3fa 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -13574,7 +13574,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) static bool init_reloc_cookie (struct elf_reloc_cookie *cookie, - struct bfd_link_info *info, bfd *abfd) + struct bfd_link_info *info, bfd *abfd, + bool keep_memory) { Elf_Internal_Shdr *symtab_hdr; const struct elf_backend_data *bed; @@ -13612,7 +13613,7 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie, info->callbacks->einfo (_("%P%X: can not read symbols: %E\n")); return false; } - if (_bfd_elf_link_keep_memory (info) ) + if (keep_memory || _bfd_elf_link_keep_memory (info)) { symtab_hdr->contents = (bfd_byte *) cookie->locsyms; info->cache_size += (cookie->locsymcount @@ -13640,7 +13641,7 @@ fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd) static bool init_reloc_cookie_rels (struct elf_reloc_cookie *cookie, struct bfd_link_info *info, bfd *abfd, - asection *sec) + asection *sec, bool keep_memory) { if (sec->reloc_count == 0) { @@ -13651,7 +13652,7 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie, { cookie->rels = _bfd_elf_link_info_read_relocs (abfd, info, sec, NULL, NULL, - _bfd_elf_link_keep_memory (info)); + keep_memory || _bfd_elf_link_keep_memory (info)); if (cookie->rels == NULL) return false; cookie->rel = cookie->rels; @@ -13677,11 +13678,12 @@ fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie, static bool init_reloc_cookie_for_section (struct elf_reloc_cookie *cookie, struct bfd_link_info *info, - asection *sec) + asection *sec, bool keep_memory) { - if (!init_reloc_cookie (cookie, info, sec->owner)) + if (!init_reloc_cookie (cookie, info, sec->owner, keep_memory)) goto error1; - if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec)) + if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec, + keep_memory)) goto error2; return true; @@ -13892,7 +13894,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info, { struct elf_reloc_cookie cookie; - if (!init_reloc_cookie_for_section (&cookie, info, sec)) + if (!init_reloc_cookie_for_section (&cookie, info, sec, false)) ret = false; else { @@ -13910,7 +13912,14 @@ _bfd_elf_gc_mark (struct bfd_link_info *info, { struct elf_reloc_cookie cookie; - if (!init_reloc_cookie_for_section (&cookie, info, eh_frame)) + /* NB: When --no-keep-memory is used, the symbol table and + relocation info for eh_frame are freed after they are retrieved + for each text section in the input object. If an input object + has many text sections, the same data is retrieved and freed + many times which can take a very long time. Always keep the + symbol table and relocation info for eh_frame to avoid it. */ + if (!init_reloc_cookie_for_section (&cookie, info, eh_frame, + true)) ret = false; else { @@ -14350,13 +14359,14 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED, if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) continue; - if (!init_reloc_cookie (&cookie, info, ibfd)) + if (!init_reloc_cookie (&cookie, info, ibfd, false)) return false; for (sec = ibfd->sections; sec; sec = sec->next) { if (startswith (bfd_section_name (sec), ".eh_frame_entry") - && init_reloc_cookie_rels (&cookie, info, ibfd, sec)) + && init_reloc_cookie_rels (&cookie, info, ibfd, sec, + false)) { _bfd_elf_parse_eh_frame_entry (info, sec, &cookie); fini_reloc_cookie_rels (&cookie, sec); @@ -14401,7 +14411,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) continue; sec = bfd_get_section_by_name (sub, ".eh_frame"); - while (sec && init_reloc_cookie_for_section (&cookie, info, sec)) + while (sec && init_reloc_cookie_for_section (&cookie, info, sec, + false)) { _bfd_elf_parse_eh_frame (sub, info, sec, &cookie); if (elf_section_data (sec)->sec_info @@ -14913,7 +14924,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) continue; - if (!init_reloc_cookie_for_section (&cookie, info, i)) + if (!init_reloc_cookie_for_section (&cookie, info, i, false)) return -1; if (_bfd_discard_section_stabs (abfd, i, @@ -14944,7 +14955,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) continue; - if (!init_reloc_cookie_for_section (&cookie, info, i)) + if (!init_reloc_cookie_for_section (&cookie, info, i, false)) return -1; _bfd_elf_parse_eh_frame (abfd, info, i, &cookie); @@ -15009,7 +15020,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) continue; - if (!init_reloc_cookie_for_section (&cookie, info, i)) + if (!init_reloc_cookie_for_section (&cookie, info, i, false)) return -1; if (_bfd_elf_parse_sframe (abfd, info, i, &cookie)) @@ -15045,7 +15056,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) if (bed->elf_backend_discard_info != NULL) { - if (!init_reloc_cookie (&cookie, info, abfd)) + if (!init_reloc_cookie (&cookie, info, abfd, false)) return -1; if ((*bed->elf_backend_discard_info) (abfd, &cookie, info)) From patchwork Fri Mar 15 12:24:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 87241 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EDEF4385DC0E for ; Fri, 15 Mar 2024 12:25:52 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com [IPv6:2607:f8b0:4864:20::62c]) by sourceware.org (Postfix) with ESMTPS id E12073857B8E for ; Fri, 15 Mar 2024 12:24:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E12073857B8E 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 E12073857B8E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505473; cv=none; b=J1/zc5TYWqlIdLhtPWjJiKkn+kXVeAQB76+ZLlmVCjj35haXvCiA4hf03IR2Uk3BK003a7h5ocPoJaoSfyDs95HSIcnmVvezmxaIej6fh6yopqA4nsjhac1F3on5iqlvV6ez4j8ZU92Zdq8UEbDcceFYuoOZ5iPRJsOiFSJri8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710505473; c=relaxed/simple; bh=eeCa47Jj0zR3TGDD+KItQpICX0XkeyFWWixSGkuqbOA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=na3pAnVr9ptLf1Pthprx+e2rv/q8jZXzReCeKL6hliFGCfVOHyn7dRMZvvCmX/PtdIOz9TNThjpLsBznLU+3aXliM+ucczl6KZn9WffWCraKBLGXWiETtqZl1CPoVbJcWE26CEz6c9fk1nr8PwgIqDq8lHHk2wYbPWFBONOmIvg= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-1dca3951ad9so14583465ad.3 for ; Fri, 15 Mar 2024 05:24:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710505469; x=1711110269; 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=ko4/QQ1fjofafjkuGyJkLrRwvvanIEOrs98j6+dER6U=; b=JwF9l4wP8zNoiHU2F35KG8PzgBokemE3ALY2Vg5no75txpcg2LzT7kYfvhf0Icg9Ue TCsD01foTJvDUlRJ2H/L0DBsIKCLYUNejkNfzseOd9fTBdPMu8k3M+QZa27546jRu1KE lluG9dZRgTD4SllSABqK27h/4+Fkkxr9qcAC+6xieKaHR+zhB1cFzdhyoBTfy1EAx+Ub AlZkdERDXWJjjuPCUgKV51AWITJv+5gcVFBoa+Xk4PWCEHDxP1CC0X6bfXY6xJqMQfnn rm7I6YWTdDDZrATPqbADTEXtP1ZxwenGIRJkDkUBydyP+lW5ERAeGWsLqjqNKP/l2Tjp lFPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710505469; x=1711110269; 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=ko4/QQ1fjofafjkuGyJkLrRwvvanIEOrs98j6+dER6U=; b=fEUTB4EL337175W45IlX9Q/D9a57WD/JSxvSIBHnLGt5UYv63svCcDLDL2d25JQa+A zfUbDu0F0vzHtoDQjf8/mPKUNJn7w6Qt1MIB2Z7zWl6Ai0diDtYMOdGH2O1TSTxJWOUK HNHQLRt62Lif9AmRztEbZOJ8M7zeCEnPDFYLP2n6iKmvIj2Hhbhbjx5+varE/JwUiYYQ a+A9YKpic7b58GszfllB0wOPwJ6eay2i9mCKv/6tg+Ccb8MiJUX2IJ3IumLYcxoYmAae MaKlZFqXVOrgXFhdT9QccJ9wU2bzWXEgt2GeZjYBMAPUg5XrF063gP3TWYPKJ8RUjvno iuPA== X-Gm-Message-State: AOJu0YxVLgzX5YmhQk2GLFbAzvgKWe5PvSzydin/IWsKCickvUFZ5TPt +QeQvpwaw5yOB8jDijW8dwExYDJCGoA7sNII7zjMIPbhS9q3jn7uPLWj0eAq X-Google-Smtp-Source: AGHT+IFBifb489H+ceZ8Rl8a3Pe9V9bTPKAa1PzldItkjGx2noVtWBFSwXxTA9+tGUStQq+dtiI6lA== X-Received: by 2002:a17:902:d552:b0:1dd:e15d:6bb6 with SMTP id z18-20020a170902d55200b001dde15d6bb6mr5459413plf.17.1710505468875; Fri, 15 Mar 2024 05:24:28 -0700 (PDT) Received: from gnu-cfl-3.localdomain ([172.58.89.72]) by smtp.gmail.com with ESMTPSA id n3-20020a170902e54300b001def088c036sm1343565plf.19.2024.03.15.05.24.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 05:24:27 -0700 (PDT) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id C08FF74071D; Fri, 15 Mar 2024 05:24:23 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com, sam@gentoo.org, amodra@gmail.com Subject: [PATCH v11 6/6] elf: Add _bfd_elf_link_m[un]map_section_contents Date: Fri, 15 Mar 2024 05:24:23 -0700 Message-ID: <20240315122423.1963285-7-hjl.tools@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315122423.1963285-1-hjl.tools@gmail.com> References: <20240315122423.1963285-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3020.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org 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 | 33 +++++++++++++++++++++-------- 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b9ec590cd4e..c386af3549f 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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 *); diff --git a/bfd/elf.c b/bfd/elf.c index cb47c499704..f66ac9289df 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -14388,10 +14388,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); @@ -14415,16 +14417,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 @@ -14464,3 +14491,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 +} diff --git a/bfd/elflink.c b/bfd/elflink.c index 4eb6ce5b3fa..386f64e9517 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11440,7 +11440,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; } @@ -11998,6 +11999,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; @@ -12436,13 +12440,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; @@ -12478,10 +12486,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)