]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf: Don't cache symbol nor relocation tables with mmap
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 28 Feb 2024 22:34:33 +0000 (14:34 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 3 Apr 2024 16:11:03 +0000 (09:11 -0700)
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/

* elf32-i386.c (elf_i386_scan_relocs): Remove
_bfd_link_keep_memory.
* elf64-x86-64.c (elf_x86_64_scan_relocs): Likewise.
* elflink.c (_bfd_elf_link_keep_memory): New.
(_bfd_elf_link_iterate_on_relocs): Replace _bfd_link_keep_memory
with _bfd_elf_link_keep_memory.
(elf_link_add_object_symbols): Likewise.
(init_reloc_cookie): Likewise.
(init_reloc_cookie_rels): Likewise.
* libbfd-in.h (_bfd_link_keep_memory): Removed.
* linker.c (_bfd_link_keep_memory): Likewise.
* libbfd.h: Regenerated.

bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elflink.c
bfd/libbfd-in.h
bfd/libbfd.h
bfd/linker.c

index fa1846881d3933ec2faadf069760c3a667278597..6183d962a831437157734ff43c2a755291932f0e 100644 (file)
@@ -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_munmap_section_contents (sec, contents);
       else
        {
index ebfd455a822a7a609f48a1e98112ec99a85de520..60aa18025525a55b67f14919a3d941649d95546d 100644 (file)
@@ -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_munmap_section_contents (sec, contents);
       else
        {
index 7e9f4c7f0b042db2fbb546731b395fb80148ee05..7a33da0a96cb1270f328f774fc4617655f31d619 100644 (file)
@@ -49,6 +49,53 @@ struct elf_info_failed
 static bool _bfd_elf_fix_symbol_flags
   (struct elf_link_hash_entry *, struct elf_info_failed *);
 
+/* Return false if linker should avoid caching relocation information
+   and symbol tables of input files in memory.  */
+
+static 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;
+}
+
 asection *
 _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
                             unsigned long r_symndx,
@@ -4182,10 +4229,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 +5597,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;
 
@@ -13616,7 +13661,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
@@ -13653,9 +13698,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;
index 889b221a9508d4aa031ee7094499227be39a8533..7bfc58f12d81e3ad2e40551b34dd89b3bf0a0d03 100644 (file)
@@ -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;
index 0676f461382c56af52bdc2e5631ce4d62e168224..bed7d88d4ecfd707866281dbb09985eb39269a58 100644 (file)
@@ -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;
index 36cca9624c281f4ba21efb211a665a8d353b0194..eb42a78b622e09a58f517a23a8d9ab9d88a8d463 100644 (file)
@@ -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;
-}