commit: 56cd194bbf2a0a211d1818b4b42ab0c74893bb18 Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Sat Oct 11 00:46:39 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sat Oct 11 00:46:48 2025 +0000 URL: https://gitweb.gentoo.org/proj/toolchain/binutils-patches.git/commit/?id=56cd194b
9999: update patch from ML Signed-off-by: Sam James <sam <AT> gentoo.org> ...-internal-symbol-table-in-relocatable-BFD.patch | 522 ++++++++++++--------- 1 file changed, 309 insertions(+), 213 deletions(-) diff --git a/9999/0005-elf-Cache-internal-symbol-table-in-relocatable-BFD.patch b/9999/0005-elf-Cache-internal-symbol-table-in-relocatable-BFD.patch index acae3cf..f829ffc 100644 --- a/9999/0005-elf-Cache-internal-symbol-table-in-relocatable-BFD.patch +++ b/9999/0005-elf-Cache-internal-symbol-table-in-relocatable-BFD.patch @@ -1,25 +1,45 @@ -From 13058a8b8feb26ddafb62995f164d81dce02979c Mon Sep 17 00:00:00 2001 +From 6081e4356a0e4f9932a05af0871490fc54e15113 Mon Sep 17 00:00:00 2001 +Message-ID: <6081e4356a0e4f9932a05af0871490fc54e15113.1760143572.git....@gentoo.org> From: "H.J. Lu" <[email protected]> -Date: Thu, 9 Oct 2025 13:16:19 +0800 +Date: Sat, 11 Oct 2025 07:18:50 +0800 Subject: [PATCH] elf: Cache full internal symbol table for relocatable input -Cache internal symbol table for relocatable input and use the internal -symbol table cache for both local and global symbols to avoid swapping in -the same symbol table repeatedly for --gc-sections. This improves linker ---gc-sections speed by ~20x. +Add bfd_elf_get_elf_syms_cached to cache internal symbol table for +relocatable input and use the internal symbol table cache for both local +and global symbols to avoid swapping in the same symbol table repeatedly +for --gc-sections. This improves linker --gc-sections speed by ~2x for +PR ld/33530. -Most backends cache the local symbol table in symtab_hdr->contents. But -some backends cache something else in it. Since symtab_hdr->contents may -point to the middle of the internal symbol table cache, we can release -symtab_hdr->contents only when no backends cache the local symbol table -in it. +elf_link_input_bfd is updated to not to pass preallocated buffers to +bfd_elf_get_elf_syms_cache. + +Data to link the 3.1GB clang executable in LLVM 21 debug build on +Linux/x86-64 with 32GB RAM is: + + before after improvement +user 48.29 46.45 3.8% +system 7.82 5.47 30% +total 56.1 51.92 7% +maximum set(GB) 10.5 10.7 -0.2% +page faults 2535779 2509896 0.1% + +and data to link the 308M cc1plus executable in GCC 16 stage 1 build is: + + before after improvement +user 3.56 3.49 0.2% +system 0.66 0.58 12% +total 4.22 4.07 0.3% +maximum set(MB) 969 992 -2.4% +page faults 992692 1016732 0.1% bfd/ PR ld/33530 - * elf-bfd.h (elf_obj_tdata): Add symtab and keep_symtab. + * elf-bfd.h (elf_obj_tdata): Add symtab. (bfd_elf_get_elf_syms): Remove the Elf_External_Sym_Shndx pointer argument. + (bfd_elf_get_elf_syms_cached): New function. + (bfd_elf_free_symtab): Likewise. * elf-eh-frame.c (adjust_eh_frame_local_symbols): Changed to return void. (_bfd_elf_discard_section_eh_frame): Updated. Don't cache @@ -30,6 +50,15 @@ bfd/ * elf-m10300.c (mn10300_elf_check_relocs): Likewise. (mn10300_elf_relax_section): Likewise. (mn10300_elf_get_relocated_section_contents): Likewise. + * elf.c (bfd_elf_get_elf_syms): Drop the Elf_External_Sym_Shndx + pointer argument. Renamed to ... + (bfd_elf_get_elf_syms_cached): This. Cache internal symbol + table. + (bfd_elf_get_elf_syms): Call bfd_elf_get_elf_syms_cached. + (group_signature): Call bfd_elf_get_elf_syms_cached instead of + bfd_elf_get_elf_syms. + (bfd_sym_from_r_symndx): Likewise. + (_bfd_elf_free_cached_info): Free internal symbol table cache. * elf32-arc.c (arc_elf_relax_section): Likewise. * elf32-arm.c (cmse_scan): Likewise. (elf32_arm_size_stubs): Likewise. @@ -92,34 +121,25 @@ bfd/ (ppc64_elf_late_size_sections): Likewise. (ppc64_elf_layout_multitoc): Likewise. (got_and_plt_relr_for_local_syms): Likewise. - * elfnn-aarch64.c (_bfd_aarch64_add_call_stub_entries): Likewise. - (bfd_elfNN_aarch64_init_maps): Likewise. - * elfnn-ia64.c (elfNN_ia64_relax_section): Likewise. - * elfnn-kvx.c (elfNN_kvx_size_stubs): Likewise. - * elfnn-loongarch.c (_bfd_riscv_relax_section): Likewise. - * elfxx-mips.c (_bfd_mips_elf_relax_section): Likewise. - * elf.c (bfd_elf_get_elf_syms): Drop the Elf_External_Sym_Shndx - pointer argument. Only allow the full external symbol table. - Cache internal symbol table. - (group_signature): Update the bfd_elf_get_elf_syms call. - (bfd_sym_from_r_symndx): Likewise. - (_bfd_elf_free_cached_info): Free internal symbol table cache. - * elfcode.h (elf_slurp_symbol_table): Don't free internal symbol - buffer. - * elflink.c (bfd_elf_link_record_local_dynamic_symbol): Update - the bfd_elf_get_elf_syms call. - (elf_link_is_defined_archive_symbol): Likewise. Free cached - internal symbol buffer unless it should be kept. - (elf_link_add_object_symbols): Update the bfd_elf_get_elf_syms - call. Free cached internal symbol buffer. - (bfd_elf_match_symbols_in_sections): Update the - bfd_elf_get_elf_syms call. Don't free the internal symbol table. + * elfcode.h (elf_slurp_symbol_table): Call + bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms. + Don't free internal symbol buffer. + * elflink.c (bfd_elf_link_record_local_dynamic_symbol): Call + bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms. + (elf_link_is_defined_archive_symbol): Likewise. Free internal + symbol table cache. + (elf_link_add_object_symbols): Call bfd_elf_get_elf_syms_cached + instead of bfd_elf_get_elf_syms. Free internal symbol table + cache if it has been changed. + (bfd_elf_match_symbols_in_sections): Call + bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms. + Don't free the internal symbol table. (elf_final_link_info): Remove external_syms, locsym_shndx and internal_syms. - (elf_link_check_versioned_symbol): Update the bfd_elf_get_elf_syms - call. - (elf_link_input_bfd): Likewise. Don't use symtab_hdr->contents - for internal symbol table. + (elf_link_check_versioned_symbol): Call + bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms. + (elf_link_input_bfd): Likewise. Don't pass pre-allocated + buffer to bfd_elf_get_elf_syms_cached. (elf_final_link_free): Updated. (bfd_elf_final_link): Don't set flinfo.external_syms, flinfo.internal_syms nor flinfo.locsym_shndx. @@ -135,6 +155,12 @@ bfd/ (bfd_elf_discard_info): Replace fini_reloc_cookie_for_section with fini_reloc_cookie_rels. Don't call fini_reloc_cookie. (bfd_elf_parse_eh_frame_entries): Updated. + * elfnn-aarch64.c (_bfd_aarch64_add_call_stub_entries): Likewise. + (bfd_elfNN_aarch64_init_maps): Likewise. + * elfnn-ia64.c (elfNN_ia64_relax_section): Likewise. + * elfnn-kvx.c (elfNN_kvx_size_stubs): Likewise. + * elfnn-loongarch.c (_bfd_riscv_relax_section): Likewise. + * elfxx-mips.c (_bfd_mips_elf_relax_section): Likewise. * elfxx-x86.c (_bfd_x86_elf_link_relax_section): Don't use use symtab_hdr->contents for internal symbol table. Set keep_symtab if the symbol table has been updated. @@ -142,19 +168,20 @@ bfd/ libctf/ PR ld/33530 - * ctf-open-bfd.c (ctf_bfdopen_ctfsect): Free internal symbol - table cache. + * ctf-open-bfd.c (ctf_bfdopen_ctfsect): Call + bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms. + Free internal symbol table cache. Signed-off-by: H.J. Lu <[email protected]> --- - bfd/elf-bfd.h | 11 ++- - bfd/elf-eh-frame.c | 17 ++--- + bfd/elf-bfd.h | 19 ++++- + bfd/elf-eh-frame.c | 17 +---- bfd/elf-m10200.c | 4 +- bfd/elf-m10300.c | 10 +-- - bfd/elf.c | 131 ++++++++++++++++++++++++++--------- + bfd/elf.c | 167 +++++++++++++++++++++++++++++++---------- bfd/elf32-arc.c | 2 +- bfd/elf32-arm.c | 7 +- - bfd/elf32-avr.c | 12 ++-- + bfd/elf32-avr.c | 12 +-- bfd/elf32-bfin.c | 2 +- bfd/elf32-cr16.c | 6 +- bfd/elf32-crx.c | 4 +- @@ -164,7 +191,7 @@ Signed-off-by: H.J. Lu <[email protected]> bfd/elf32-h8300.c | 4 +- bfd/elf32-hppa.c | 2 +- bfd/elf32-ip2k.c | 2 +- - bfd/elf32-m32c.c | 8 ++- + bfd/elf32-m32c.c | 8 +- bfd/elf32-m68hc11.c | 2 +- bfd/elf32-m68hc1x.c | 2 +- bfd/elf32-m68k.c | 2 +- @@ -185,21 +212,21 @@ Signed-off-by: H.J. Lu <[email protected]> bfd/elf64-hppa.c | 2 +- bfd/elf64-ia64-vms.c | 4 +- bfd/elf64-mmix.c | 2 +- - bfd/elf64-ppc.c | 12 ++-- - bfd/elfcode.h | 8 +-- - bfd/elflink.c | 152 ++++++++++++----------------------------- + bfd/elf64-ppc.c | 12 +-- + bfd/elfcode.h | 10 +-- + bfd/elflink.c | 162 +++++++++++---------------------------- bfd/elfnn-aarch64.c | 4 +- bfd/elfnn-ia64.c | 2 +- bfd/elfnn-kvx.c | 2 +- bfd/elfnn-loongarch.c | 2 +- bfd/elfnn-riscv.c | 2 +- bfd/elfxx-mips.c | 2 +- - bfd/elfxx-x86.c | 24 +++---- - libctf/ctf-open-bfd.c | 5 +- - 49 files changed, 243 insertions(+), 262 deletions(-) + bfd/elfxx-x86.c | 22 ++++-- + libctf/ctf-open-bfd.c | 6 +- + 49 files changed, 293 insertions(+), 267 deletions(-) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h -index 5d19529d972..b7061e55b59 100644 +index 5d19529d972..b0bd8f4d589 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2165,6 +2165,11 @@ struct elf_obj_tdata @@ -214,26 +241,34 @@ index 5d19529d972..b7061e55b59 100644 /* List of GNU properties. Will be updated by setup_gnu_properties after all input GNU properties are merged for output. */ elf_property_list *properties; -@@ -2207,6 +2212,9 @@ struct elf_obj_tdata - symbols. */ - unsigned int bad_symtab : 1; - -+ /* Set if the symbol table cache should be kept. */ -+ unsigned int keep_symtab : 1; -+ - /* Set if DT_FLAGS_1 has DF_1_PIE set. */ - unsigned int is_pie : 1; - -@@ -2297,8 +2305,7 @@ extern unsigned int _bfd_elf_section_from_bfd_section +@@ -2297,8 +2302,9 @@ extern unsigned int _bfd_elf_section_from_bfd_section extern char *bfd_elf_string_from_elf_section (bfd *, unsigned, unsigned); extern Elf_Internal_Sym *bfd_elf_get_elf_syms - (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *, - Elf_External_Sym_Shndx *); ++ (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *); ++extern Elf_Internal_Sym *bfd_elf_get_elf_syms_cached + (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *); extern char * bfd_elf_get_str_section (bfd *, unsigned int); extern const char *bfd_elf_sym_name (bfd *, Elf_Internal_Shdr *, Elf_Internal_Sym *, asection *); +@@ -3333,6 +3339,15 @@ bfd_section_is_ctf (const asection *sec) + return startswith (name, ".ctf") && (name[4] == 0 || name[4] == '.'); + } + ++/* Free ELF symbol table cache. */ ++ ++static inline void ++bfd_elf_free_symtab (bfd *abfd) ++{ ++ free (elf_tdata (abfd)->symtab); ++ elf_tdata (abfd)->symtab = NULL; ++} ++ + #ifdef __cplusplus + } + #endif diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 4eda3c991bb..bd2c85291fb 100644 --- a/bfd/elf-eh-frame.c @@ -353,7 +388,7 @@ index b381bb9037c..373290cbe4a 100644 goto error_return; } diff --git a/bfd/elf.c b/bfd/elf.c -index bde7414ee21..9e220f0a0d7 100644 +index bde7414ee21..472fb5da55e 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -428,21 +428,20 @@ bfd_elf_string_from_elf_section (bfd *abfd, @@ -369,20 +404,23 @@ index bde7414ee21..9e220f0a0d7 100644 - Returns a pointer to the internal symbol buffer (malloced if necessary) - or NULL if there were no symbols or some kind of problem. */ + symbols, and symbol section index extensions, respectively. Returns -+ a pointer to the internal symbol buffer (malloced if necessary) or -+ NULL if there were no symbols or some kind of problem. */ ++ a pointer to the internal symbol cache or NULL if there were no ++ symbols or some kind of problem. */ Elf_Internal_Sym * - bfd_elf_get_elf_syms (bfd *ibfd, - Elf_Internal_Shdr *symtab_hdr, +-bfd_elf_get_elf_syms (bfd *ibfd, +- Elf_Internal_Shdr *symtab_hdr, - size_t symcount, - size_t symoffset, -+ size_t partial_symcount, -+ size_t partial_symoffset, - Elf_Internal_Sym *intsym_buf, +- Elf_Internal_Sym *intsym_buf, - void *extsym_buf, - Elf_External_Sym_Shndx *extshndx_buf) -+ void *partial_extsym_buf) ++bfd_elf_get_elf_syms_cached (bfd *ibfd, ++ Elf_Internal_Shdr *symtab_hdr, ++ size_t partial_symcount, ++ size_t partial_symoffset, ++ Elf_Internal_Sym *intsym_buf, ++ void *partial_extsym_buf) { Elf_Internal_Shdr *shndx_hdr; void *alloc_ext; @@ -400,30 +438,33 @@ index bde7414ee21..9e220f0a0d7 100644 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) abort (); -@@ -474,6 +478,22 @@ bfd_elf_get_elf_syms (bfd *ibfd, +@@ -474,6 +478,25 @@ bfd_elf_get_elf_syms (bfd *ibfd, return elf_tdata (ibfd)->dt_symtab + symoffset; } + if (elf_tdata (ibfd)->symtab != NULL) + { -+ /* NB: Should extsym_buf be cached? */ ++ /* Since extsym_buf isn't cached, free the symbol table cache and ++ re-read the symbol table. */ + if (partial_extsym_buf != NULL) -+ abort (); -+ -+ if (intsym_buf != NULL) ++ bfd_elf_free_symtab (ibfd); ++ else + { -+ memcpy (intsym_buf, elf_tdata (ibfd)->symtab + symoffset, -+ symcount * sizeof (*intsym_buf)); -+ return intsym_buf; ++ if (intsym_buf != NULL) ++ { ++ memcpy (intsym_buf, elf_tdata (ibfd)->symtab + symoffset, ++ symcount * sizeof (*intsym_buf)); ++ return intsym_buf; ++ } ++ else ++ return elf_tdata (ibfd)->symtab + symoffset; + } -+ else -+ return elf_tdata (ibfd)->symtab + symoffset; + } + /* Normal syms might have section extension entries. */ shndx_hdr = NULL; if (elf_symtab_shndx_list (ibfd) != NULL) -@@ -506,19 +526,31 @@ bfd_elf_get_elf_syms (bfd *ibfd, +@@ -506,19 +529,31 @@ bfd_elf_get_elf_syms (bfd *ibfd, } } @@ -458,7 +499,7 @@ index bde7414ee21..9e220f0a0d7 100644 if (bfd_seek (ibfd, pos, SEEK_SET) != 0 || !_bfd_mmap_read_temporary (&extsym_buf, &alloc_ext_size, &alloc_ext, ibfd, false)) -@@ -551,22 +583,24 @@ bfd_elf_get_elf_syms (bfd *ibfd, +@@ -551,22 +586,24 @@ bfd_elf_get_elf_syms (bfd *ibfd, } } @@ -476,17 +517,17 @@ index bde7414ee21..9e220f0a0d7 100644 - goto out1; + bfd_set_error (bfd_error_file_too_big); + goto out1; - } ++ } + alloc_intsym = (Elf_Internal_Sym *) bfd_malloc (amt); + if (alloc_intsym == NULL) + { + intsym_buf = NULL; + goto out1; -+ } -+ + } + + if (intsym_buf == NULL) + intsym_buf = alloc_intsym; - ++ /* Convert the symbols to internal form. */ - isymend = intsym_buf + symcount; - for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf, @@ -495,7 +536,7 @@ index bde7414ee21..9e220f0a0d7 100644 shndx = extshndx_buf; isym < isymend; esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL) -@@ -590,7 +624,9 @@ bfd_elf_get_elf_syms (bfd *ibfd, +@@ -590,7 +627,9 @@ bfd_elf_get_elf_syms (bfd *ibfd, { /* xgettext:c-format */ _bfd_error_handler (_("%pB symbol number %lu uses unsupported binding of %u"), @@ -506,7 +547,7 @@ index bde7414ee21..9e220f0a0d7 100644 free (alloc_intsym); intsym_buf = NULL; goto out1; -@@ -602,19 +638,42 @@ bfd_elf_get_elf_syms (bfd *ibfd, +@@ -602,18 +641,72 @@ bfd_elf_get_elf_syms (bfd *ibfd, { /* xgettext:c-format */ _bfd_error_handler (_("%pB symbol number %lu uses unsupported type of %u"), @@ -520,23 +561,19 @@ index bde7414ee21..9e220f0a0d7 100644 } } ++ /* Copy external symbol table before external symbol table buffer ++ is released by _bfd_munmap_temporary. */ + if (intsym_buf != NULL && partial_extsym_buf != NULL) -+ { -+ if (partial_symcount != symcount) -+ abort (); -+ memcpy (partial_extsym_buf, extsym_buf, extsym_buf_size); -+ } ++ memcpy (partial_extsym_buf, ++ extsym_buf + partial_symoffset * extsym_size, ++ partial_symcount * extsym_size); + out1: _bfd_munmap_temporary (alloc_extshndx, alloc_extshndx_size); out2: _bfd_munmap_temporary (alloc_ext, alloc_ext_size); -- return intsym_buf; -+ if (intsym_buf == NULL) -+ return intsym_buf; -+ -+ if (!cache_symtab) ++ if (intsym_buf == NULL || !cache_symtab) + return intsym_buf; + + elf_tdata (ibfd)->symtab = alloc_intsym; @@ -548,10 +585,43 @@ index bde7414ee21..9e220f0a0d7 100644 + } + else + return alloc_intsym + partial_symoffset; ++} ++ ++/* Read and convert symbols to internal format. ++ PARTIAL_SYMCOUNT specifies the number of symbols to read, starting ++ from symbol PARTIAL_SYMOFFSET. If INTSYM_BUF or PARTIAL_EXTSYM_BUF ++ are non-NULL, they are used to store the internal symbols, external ++ symbols, and symbol section index extensions, respectively. Returns ++ a pointer to the internal symbol buffer (malloced if necessary) or ++ NULL if there were no symbols or some kind of problem. */ ++ ++Elf_Internal_Sym * ++bfd_elf_get_elf_syms (bfd *ibfd, ++ Elf_Internal_Shdr *symtab_hdr, ++ size_t partial_symcount, ++ size_t partial_symoffset, ++ Elf_Internal_Sym *intsym_buf, ++ void *partial_extsym_buf) ++{ ++ Elf_Internal_Sym *isym ++ = bfd_elf_get_elf_syms_cached (ibfd, symtab_hdr, partial_symcount, ++ partial_symoffset, intsym_buf, ++ partial_extsym_buf); ++ if (isym == NULL ++ || intsym_buf != NULL ++ || partial_symcount == 0 ++ || elf_use_dt_symtab_p (ibfd)) ++ return isym; ++ ++ size_t amt = partial_symcount * sizeof (*intsym_buf); ++ intsym_buf = bfd_malloc (amt); ++ if (intsym_buf != NULL) ++ memcpy (intsym_buf, isym, amt); ++ bfd_elf_free_symtab (ibfd); + return intsym_buf; } - /* Look up a symbol name. */ -@@ -659,8 +718,6 @@ static const char * +@@ -659,8 +752,6 @@ static const char * group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr) { Elf_Internal_Shdr *hdr; @@ -560,16 +630,18 @@ index bde7414ee21..9e220f0a0d7 100644 Elf_Internal_Sym isym; /* First we need to ensure the symbol table is available. Make sure -@@ -675,7 +732,7 @@ group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr) +@@ -674,8 +765,8 @@ group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr) + /* Go read the symbol. */ hdr = &elf_tdata (abfd)->symtab_hdr; - if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info, +- if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info, - &isym, esym, &eshndx) == NULL) -+ &isym, NULL) == NULL) ++ if (bfd_elf_get_elf_syms_cached (abfd, hdr, 1, ghdr->sh_info, ++ &isym, NULL) == NULL) return NULL; return bfd_elf_sym_name_raw (abfd, hdr, &isym); -@@ -3029,12 +3086,10 @@ bfd_sym_from_r_symndx (struct sym_cache *cache, +@@ -3029,12 +3120,10 @@ bfd_sym_from_r_symndx (struct sym_cache *cache, if (cache->abfd != abfd || cache->indx[ent] != r_symndx) { Elf_Internal_Shdr *symtab_hdr; @@ -577,24 +649,17 @@ index bde7414ee21..9e220f0a0d7 100644 - Elf_External_Sym_Shndx eshndx; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx, +- if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx, - &cache->sym[ent], esym, &eshndx) == NULL) -+ &cache->sym[ent], NULL) == NULL) ++ if (bfd_elf_get_elf_syms_cached (abfd, symtab_hdr, 1, r_symndx, ++ &cache->sym[ent], NULL) == NULL) return NULL; if (cache->abfd != abfd) -@@ -10239,8 +10294,16 @@ _bfd_elf_free_cached_info (bfd *abfd) - free (sec_info->cies); - } +@@ -10241,6 +10330,8 @@ _bfd_elf_free_cached_info (bfd *abfd) } -+#if 0 -+ /* NB: tdata->symtab_hdr.contents may point to the middle of -+ tdata->symtab. Need to update all backends only to cache -+ the malloced memory in tdata->symtab_hdr.contents before -+ tdata->symtab_hdr.contents can be freed. */ free (tdata->symtab_hdr.contents); tdata->symtab_hdr.contents = NULL; -+#endif + free (tdata->symtab); + tdata->symtab = NULL; } @@ -1307,15 +1372,17 @@ index fdda9e0bbb3..ee15d6f0639 100644 return false; } diff --git a/bfd/elfcode.h b/bfd/elfcode.h -index 5224a1abee6..8777a08a77a 100644 +index 5224a1abee6..f8176294bc9 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h -@@ -1303,7 +1303,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic) +@@ -1302,8 +1302,8 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic) + { size_t i; - isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0, +- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0, - NULL, NULL, NULL); -+ NULL, NULL); ++ isymbuf = bfd_elf_get_elf_syms_cached (abfd, hdr, symcount, 0, ++ NULL, NULL); if (isymbuf == NULL) return -1; @@ -1337,7 +1404,7 @@ index 5224a1abee6..8777a08a77a 100644 } diff --git a/bfd/elflink.c b/bfd/elflink.c -index 3f3ea2cce51..da4da5c453a 100644 +index 3f3ea2cce51..0ab843a4924 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -851,8 +851,6 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, @@ -1349,89 +1416,119 @@ index 3f3ea2cce51..da4da5c453a 100644 if (! is_elf_hash_table (info->hash)) return 0; -@@ -869,7 +867,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, +@@ -868,8 +866,9 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, + return 0; /* Go find the symbol, so that we can find it's name. */ - if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr, +- if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr, - 1, input_indx, &entry->isym, esym, &eshndx)) -+ 1, input_indx, &entry->isym, NULL)) ++ if (!bfd_elf_get_elf_syms_cached (input_bfd, ++ &elf_tdata (input_bfd)->symtab_hdr, ++ 1, input_indx, &entry->isym, NULL)) { bfd_release (input_bfd, entry); return 0; -@@ -3745,7 +3743,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) +@@ -3744,8 +3743,8 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) + return false; /* Read in the symbol table. */ - isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, +- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, - NULL, NULL, NULL); -+ NULL, NULL); ++ isymbuf = bfd_elf_get_elf_syms_cached (abfd, hdr, extsymcount, ++ extsymoff, NULL, NULL); if (isymbuf == NULL) return false; -@@ -3767,7 +3765,11 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) +@@ -3767,7 +3766,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) } } - free (isymbuf); -+ if (!elf_tdata (abfd)->keep_symtab) -+ { -+ free (elf_tdata (abfd)->symtab); -+ elf_tdata (abfd)->symtab = NULL; -+ } ++ bfd_elf_free_symtab (abfd); return result; } -@@ -4830,7 +4832,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) +@@ -4829,8 +4828,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) + sym_hash = elf_sym_hashes (abfd); if (extsymcount != 0) { - isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, +- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, - NULL, NULL, NULL); -+ NULL, NULL); ++ isymbuf = bfd_elf_get_elf_syms_cached (abfd, hdr, extsymcount, ++ extsymoff, NULL, NULL); if (isymbuf == NULL) goto error_return; -@@ -5814,8 +5816,11 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) +@@ -4977,6 +4976,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) + (_("%pB: plugin needed to handle lto object"), abfd); + } + ++ bool symtab_changed = false; ++ + for (isym = isymbuf, isymend = PTR_ADD (isymbuf, extsymcount); + isym < isymend; + isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL)) +@@ -5013,6 +5014,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) + { + /* Treat common symbol as undefined for --no-define-common. */ + isym->st_shndx = SHN_UNDEF; ++ symtab_changed = true; + common = false; + } + discarded = false; +@@ -5086,6 +5088,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) + sec = bfd_und_section_ptr; + discarded = true; + isym->st_shndx = SHN_UNDEF; ++ symtab_changed = true; + } + else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) + value -= sec->vma; +@@ -5814,8 +5817,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) free (extversym); extversym = NULL; - free (isymbuf); - isymbuf = NULL; + -+ /* NB: Since st_shndx of symbol from discarded section is changed to -+ SHN_UNDEF, free the cached symbol table. */ -+ free (elf_tdata (abfd)->symtab); -+ elf_tdata (abfd)->symtab = NULL; ++ /* Free internal symbol table cache if it has been changed. */ ++ if (symtab_changed) ++ bfd_elf_free_symtab (abfd); if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0) { -@@ -6167,7 +6172,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) +@@ -6167,7 +6172,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) free (nondeflt_vers); free (extversym); error_free_sym: - free (isymbuf); -+ free (elf_tdata (abfd)->symtab); -+ elf_tdata (abfd)->symtab = NULL; ++ bfd_elf_free_symtab (abfd); error_return: return false; } -@@ -8809,7 +8815,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, +@@ -8808,8 +8813,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, + if (ssymbuf1 == NULL) { - isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0, +- isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0, - NULL, NULL, NULL); -+ NULL, NULL); ++ isymbuf1 = bfd_elf_get_elf_syms_cached (bfd1, hdr1, symcount1, ++ 0, NULL, NULL); if (isymbuf1 == NULL) goto done; -@@ -8823,7 +8829,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, +@@ -8822,8 +8827,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, + if (ssymbuf1 == NULL || ssymbuf2 == NULL) { - isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0, +- isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0, - NULL, NULL, NULL); -+ NULL, NULL); ++ isymbuf2 = bfd_elf_get_elf_syms_cached (bfd2, hdr2, symcount2, ++ 0, NULL, NULL); if (isymbuf2 == NULL) goto done; -@@ -9013,8 +9019,6 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, +@@ -9013,8 +9018,6 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, done: free (symtable1); free (symtable2); @@ -1440,7 +1537,7 @@ index 3f3ea2cce51..da4da5c453a 100644 return result; } -@@ -9056,14 +9060,6 @@ struct elf_final_link_info +@@ -9056,14 +9059,6 @@ struct elf_final_link_info void *external_relocs; /* Buffer large enough to hold internal relocs of any section. */ Elf_Internal_Rela *internal_relocs; @@ -1455,16 +1552,18 @@ index 3f3ea2cce51..da4da5c453a 100644 /* Array large enough to hold a symbol index for each local symbol of any input BFD. */ long *indices; -@@ -10666,7 +10662,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, +@@ -10665,8 +10660,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, + if (extsymcount == 0) continue; - isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff, +- isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff, - NULL, NULL, NULL); -+ NULL, NULL); ++ isymbuf = bfd_elf_get_elf_syms_cached (input, hdr, extsymcount, ++ extsymoff, NULL, NULL); if (isymbuf == NULL) return false; -@@ -11410,7 +11406,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) +@@ -11410,7 +11405,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) Elf_Internal_Shdr *symtab_hdr; size_t locsymcount; size_t extsymoff; @@ -1473,19 +1572,16 @@ index 3f3ea2cce51..da4da5c453a 100644 Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; long *pindex; -@@ -11456,13 +11452,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) - ? -1 : ~elf_gnu_osabi_retain)); - - /* Read the local symbols. */ -- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; -- if (isymbuf == NULL && locsymcount != 0) -+ if (locsymcount != 0) +@@ -11459,10 +11454,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL && locsymcount != 0) { - isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, +- isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, - flinfo->internal_syms, - flinfo->external_syms, - flinfo->locsym_shndx); -+ NULL, NULL); ++ isymbuf = bfd_elf_get_elf_syms_cached (input_bfd, symtab_hdr, ++ locsymcount, 0, NULL, NULL); if (isymbuf == NULL) return false; } @@ -1576,10 +1672,12 @@ index 3f3ea2cce51..da4da5c453a 100644 - if (cookie->locsyms == NULL && cookie->locsymcount != 0) + if (cookie->locsymcount != 0) { - cookie->locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, - cookie->locsymcount, 0, +- cookie->locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, +- cookie->locsymcount, 0, - NULL, NULL, NULL); -+ NULL, NULL); ++ cookie->locsyms = bfd_elf_get_elf_syms_cached (abfd, symtab_hdr, ++ cookie->locsymcount, ++ 0, NULL, NULL); if (cookie->locsyms == NULL) { info->callbacks->einfo (_("%P%X: can not read symbols: %E\n")); @@ -1678,21 +1776,17 @@ index 3f3ea2cce51..da4da5c453a 100644 sec = bfd_get_next_section_by_name (NULL, sec); } } -@@ -14784,6 +14711,13 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) +@@ -14784,6 +14711,9 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) return false; } + -+ if (!elf_tdata (sub)->keep_symtab -+ && !_bfd_elf_link_keep_memory (info)) -+ { -+ free (elf_tdata (sub)->symtab); -+ elf_tdata (sub)->symtab = NULL; -+ } ++ if (!_bfd_elf_link_keep_memory (info)) ++ bfd_elf_free_symtab (sub); } /* Allow the backend to mark additional target specific sections. */ -@@ -15239,7 +15173,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) +@@ -15239,7 +15169,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) &cookie)) changed = 1; @@ -1701,7 +1795,7 @@ index 3f3ea2cce51..da4da5c453a 100644 } } -@@ -15274,7 +15208,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) +@@ -15274,7 +15204,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) changed = 1; } @@ -1710,7 +1804,7 @@ index 3f3ea2cce51..da4da5c453a 100644 } eh_alignment = ((1 << o->alignment_power) -@@ -15339,7 +15273,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) +@@ -15339,7 +15269,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) changed = 1; } } @@ -1719,7 +1813,7 @@ index 3f3ea2cce51..da4da5c453a 100644 } /* Update the reference to the output .sframe section. Used to determine later if PT_GNU_SFRAME segment is to be generated. */ -@@ -15362,13 +15296,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) +@@ -15362,13 +15292,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) if (bed->elf_backend_discard_info != NULL) { @@ -1822,64 +1916,66 @@ index 00ef0663728..44c58362dda 100644 goto error_return; } diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c -index 140e86888a6..53083e0b54c 100644 +index 140e86888a6..3f397f5cf70 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c -@@ -1154,15 +1154,11 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED, - /* Read this BFD's local symbols. */ - if (isymbuf == NULL) - { -- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; -+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, -+ symtab_hdr->sh_info, -+ 0, NULL, NULL); +@@ -1157,9 +1157,10 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED, + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; if (isymbuf == NULL) -- { + { - isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, - symtab_hdr->sh_info, - 0, NULL, NULL, NULL); -- if (isymbuf == NULL) -- goto error_return; -- } -+ goto error_return; - } - - isym = isymbuf + r_symndx; -@@ -1345,14 +1341,10 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED, ++ isymbuf ++ = bfd_elf_get_elf_syms_cached (abfd, symtab_hdr, ++ symtab_hdr->sh_info, ++ 0, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } +@@ -1345,13 +1346,18 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED, return_status = true; error_return: - if ((unsigned char *) isymbuf != symtab_hdr->contents) -- { ++ if (keep_symbuf && (unsigned char *) isymbuf != symtab_hdr->contents) + { - /* Cache the symbol buffer if it must be kept. */ - if (keep_symbuf) - symtab_hdr->contents = (unsigned char *) isymbuf; -- else ++ /* Cache the symbol buffer if it has been changed. */ ++ size_t amt = symtab_hdr->sh_info * sizeof (*isymbuf); ++ void *buffer = bfd_malloc (amt); ++ if (buffer == NULL) ++ return_status = false; + else - free (isymbuf); -- } -+ /* If the symbol table has been updated, it must be kept since it will -+ be used later. */ -+ if (keep_symbuf) -+ elf_tdata (abfd)->keep_symtab = 1; ++ { ++ memcpy (buffer, isymbuf, amt); ++ symtab_hdr->contents = buffer; ++ } + } if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); - return return_status; diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c -index 7241de70709..205347c4e22 100644 +index 7241de70709..2ec91ffb0bf 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c -@@ -146,8 +146,9 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, +@@ -145,9 +145,9 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, + goto err; } - isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0, +- isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0, - NULL, symtab, NULL); - free (isymbuf); -+ NULL, symtab); -+ free (elf_tdata (abfd)->symtab); -+ elf_tdata (abfd)->symtab = NULL; ++ isymbuf = bfd_elf_get_elf_syms_cached (abfd, symhdr, symcount, 0, ++ NULL, symtab); ++ bfd_elf_free_symtab (abfd); if (isymbuf == NULL) { bfderrstr = N_("cannot read symbol table"); + +base-commit: 552ddbabb5d28b301c660ddeecae19510ed4aa30 -- -GitLab +2.51.0
