From: Nick Alcock Date: Fri, 25 Apr 2025 20:28:25 +0000 (+0100) Subject: bfd, ld: allow the disabling of CTF deduplication; BTF linking X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1cea8a8ce757eb5e99f228abdf73cd62578b7745;p=thirdparty%2Fbinutils-gdb.git bfd, ld: allow the disabling of CTF deduplication; BTF linking This first half of ld support for BTF deduplication adds a facility to GNU ld and BFD to entirely disable CTF or BTF deduplication via the new --disable-ctf-dedup linker option, and (slightly entangled with it) modifies the existing BFD CTF support so that it can also deduplicate BTF. Determining whether deduplication is disabled when all you have is a section requires a bit of digging around and the proxying of of _bfd_get_link_info into bfd-elf.h via a new _bfd_elf_get_link_info, to dodge include ordering problems. (Note that BTF deduplication support is not yet complete: in particular, relocs into BTF sections don't get handled at all yet.) --- diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index d2bf8e5cbae..0dde5dd2d8e 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -37,6 +37,14 @@ extern "C" { #endif +#ifndef ATTRIBUTE_HIDDEN +#if HAVE_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif +#endif + /* The number of entries in a section is its size divided by the size of a single entry. This is normally only applicable to reloc and symbol table sections. @@ -3156,6 +3164,9 @@ extern void _bfd_elf_link_munmap_section_contents extern struct elf_link_hash_entry * _bfd_elf_get_link_hash_entry (struct elf_link_hash_entry **, unsigned int, Elf_Internal_Shdr *); +extern struct bfd_link_info *_bfd_elf_get_link_info (bfd *) + ATTRIBUTE_HIDDEN; + /* Large common section. */ extern asection _bfd_elf_large_com_section; @@ -3305,12 +3316,21 @@ extern asection _bfd_elf_large_com_section; || (H)->start_stop \ || ((INFO)->dynamic && !(H)->dynamic))) -/* Determine if a section contains CTF data, using its name. */ +/* Determine if a section contains data deduplicable using the libctf + deduplicator, using its name. */ static inline bool -bfd_section_is_ctf (const asection *sec) +bfd_section_is_libctf_deduppable (const asection *sec) { const char *name = bfd_section_name (sec); - return startswith (name, ".ctf") && (name[4] == 0 || name[4] == '.'); + struct bfd_link_info *info; + + info = _bfd_elf_get_link_info (sec->owner); + + if (!info || info->ctf_disabled) + return false; + + return (startswith (name, ".ctf") || startswith (name, ".BTF")) + && (name[4] == 0 || name[4] == '.'); } #ifdef __cplusplus diff --git a/bfd/elf.c b/bfd/elf.c index 3f8bc838bfb..768de17c678 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -2969,6 +2969,7 @@ bfd_section_from_elf_index (bfd *abfd, unsigned int sec_index) static const struct bfd_elf_special_section special_sections_b[] = { + { STRING_COMMA_LEN (".BTF"), 0, SHT_PROGBITS, 0 }, { STRING_COMMA_LEN (".bss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, { NULL, 0, 0, 0, 0 } }; @@ -6561,7 +6562,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, || (abfd->is_linker_output && hdr->bfd_section != NULL && (hdr->sh_name == -1u - || bfd_section_is_ctf (hdr->bfd_section))) + || bfd_section_is_libctf_deduppable (hdr->bfd_section))) || hdr == i_shdrpp[elf_onesymtab (abfd)] || (elf_symtab_shndx_list (abfd) != NULL && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx]) @@ -6750,13 +6751,16 @@ find_section_in_list (unsigned int i, elf_section_list * list) VMAs must be known before this is called. Reloc sections come in two flavours: Those processed specially as - "side-channel" data attached to a section to which they apply, and - those that bfd doesn't process as relocations. The latter sort are - stored in a normal bfd section by bfd_section_from_shdr. We don't - consider the former sort here, unless they form part of the loadable - image. Reloc sections not assigned here (and compressed debugging - sections and CTF sections which nothing else in the file can rely - upon) will be handled later by assign_file_positions_for_relocs. + "side-channel" data attached to a section to which they apply, and those + that bfd doesn't process as relocations. The latter sort are stored in a + normal bfd section by bfd_section_from_shdr. We don't consider the + former sort here, unless they form part of the loadable image. Reloc + sections not assigned here (and compressed debugging sections and CTF or + BTF sections which nothing else in the file can rely upon) will be + handled later by assign_file_positions_for_relocs. + + XXX UPTODO BTF sections can be depended upon by other sections: what to do + about them? We also don't set the positions of the .symtab and .strtab here. */ @@ -6796,7 +6800,7 @@ assign_file_positions_except_relocs (bfd *abfd, || (abfd->is_linker_output && hdr->bfd_section != NULL && (hdr->sh_name == -1u - || bfd_section_is_ctf (hdr->bfd_section))) + || bfd_section_is_libctf_deduppable (hdr->bfd_section))) || i == elf_onesymtab (abfd) || (elf_symtab_shndx_list (abfd) != NULL && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx]) @@ -7046,7 +7050,7 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd) || shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA) ; - else if (bfd_section_is_ctf (sec)) + else if (bfd_section_is_libctf_deduppable (sec)) { /* Update section size and contents. */ shdrp->sh_size = sec->size; @@ -8972,7 +8976,7 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."), if (elfsym->sym.st_name != 0) elfsym->sym.st_name = _bfd_elf_strtab_offset (stt, elfsym->sym.st_name); - if (info && info->callbacks->ctf_new_symbol) + if (info && info->callbacks->ctf_new_symbol && !info->ctf_disabled) info->callbacks->ctf_new_symbol (elfsym->dest_index, &elfsym->sym); @@ -9970,7 +9974,7 @@ _bfd_elf_set_section_contents (bfd *abfd, { unsigned char *contents; - if (bfd_section_is_ctf (section)) + if (bfd_section_is_libctf_deduppable (section)) /* Nothing to do with this section: the contents are generated later. */ return true; diff --git a/bfd/elflink.c b/bfd/elflink.c index 0df19769483..516a9e02d78 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -130,6 +130,12 @@ _bfd_elf_get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes, return get_link_hash_entry (sym_hashes, symndx, symtab_hdr->sh_info); } +struct bfd_link_info * +_bfd_elf_get_link_info (bfd *abfd) +{ + return _bfd_get_link_info (abfd); +} + static struct elf_link_hash_entry * get_ext_sym_hash_from_cookie (struct elf_reloc_cookie *cookie, unsigned long r_symndx) { @@ -10467,7 +10473,8 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) /* Inform the linker of the addition of this symbol. */ - if (flinfo->info->callbacks->ctf_new_symbol) + if (flinfo->info->callbacks->ctf_new_symbol + && !flinfo->info->ctf_disabled) flinfo->info->callbacks->ctf_new_symbol (elfsym->dest_index, &elfsym->sym); @@ -11096,7 +11103,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* Inform the linker of the addition of this symbol. */ - if (flinfo->info->callbacks->ctf_new_dynsym) + if (flinfo->info->callbacks->ctf_new_dynsym + && !flinfo->info->ctf_disabled) flinfo->info->callbacks->ctf_new_dynsym (h->dynindx, &sym); bed->s->swap_symbol_out (flinfo->output_bfd, &sym, esym, 0); @@ -12918,7 +12926,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) esdo->rela.count = 0; if ((esdo->this_hdr.sh_offset == (file_ptr) -1) - && !bfd_section_is_ctf (o)) + && !bfd_section_is_libctf_deduppable (o)) { /* Cache the section contents so that they can be compressed later. Use bfd_malloc since it will be freed by @@ -13291,7 +13299,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Inform the linker of the addition of this symbol. */ - if (info->callbacks->ctf_new_dynsym) + if (info->callbacks->ctf_new_dynsym && !info->ctf_disabled) info->callbacks->ctf_new_dynsym (dynindx, &sym); bed->s->swap_symbol_out (abfd, &sym, dest, 0); @@ -13331,7 +13339,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Inform the linker of the addition of this symbol. */ - if (info->callbacks->ctf_new_dynsym) + if (info->callbacks->ctf_new_dynsym && !info->ctf_disabled) info->callbacks->ctf_new_dynsym (e->dynindx, &sym); dest = dynsym + e->dynindx * bed->s->sizeof_sym; @@ -13798,7 +13806,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (! _bfd_elf_write_section_sframe (abfd, info)) goto error_return; - if (info->callbacks->emit_ctf) + if (info->callbacks->emit_ctf && !info->ctf_disabled) info->callbacks->emit_ctf (); elf_final_link_free (abfd, &flinfo); diff --git a/include/bfdlink.h b/include/bfdlink.h index 3d4d71b3347..bb1c651aa25 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -589,6 +589,9 @@ struct bfd_link_info /* TRUE if commonpagesize is set on command-line. */ unsigned int commonpagesize_is_set : 1; + /* TRUE if BTF and CTF linking are disabled. */ + unsigned int ctf_disabled : 1; + /* Char that may appear as the first char of a symbol, but should be skipped (like symbol_leading_char) when looking up symbols in wrap_hash. Used by PowerPC Linux for 'dot' symbols. */ diff --git a/ld/ld.texi b/ld/ld.texi index 6d51ccbe572..bc2155caacf 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -1982,6 +1982,16 @@ large projects this may speed up opening the CTF and save memory in the CTF consumer at runtime. @end table +@kindex --disable-ctf-dedup +@kindex --disable-ctf-dedup +@item --disable-ctf-dedup +Disable CTF and BTF deduplication entirely. The input sections are concatenated +just like any other section. Note that concatenated CTF and BTF sections are +not in general useful: libctf and other consumers will typically read the first +portion and ignore any subsequent portions. Nonetheless, this is sometimes +useful in special circumstances, such as when the section's format is not +actually that of a CTF or BTF section but merely shares the same name. + @cindex common allocation @kindex --no-define-common @item --no-define-common diff --git a/ld/ldlang.c b/ld/ldlang.c index 011c5262f87..a714be79d8e 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -3805,6 +3805,9 @@ ldlang_open_ctf (void) int any_ctf = 0; int err; + if (link_info.ctf_disabled) + return; + LANG_FOR_EACH_INPUT_STATEMENT (file) { asection *sect; @@ -3930,14 +3933,16 @@ lang_merge_ctf (void) void ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab) { - ldemul_acquire_strings_for_ctf (ctf_output, dynstrtab); + if (!link_info.ctf_disabled) + ldemul_acquire_strings_for_ctf (ctf_output, dynstrtab); } /* Inform the emulation about the addition of a new dynamic symbol, in BFD internal format. */ void ldlang_ctf_new_dynsym (int symidx, struct elf_internal_sym *sym) { - ldemul_new_dynsym_for_ctf (ctf_output, symidx, sym); + if (!link_info.ctf_disabled) + ldemul_new_dynsym_for_ctf (ctf_output, symidx, sym); } /* Write out the CTF section. Called early, if the emulation isn't going to @@ -4011,6 +4016,9 @@ ldlang_write_ctf_late (void) static void ldlang_open_ctf (void) { + if (link_info.ctf_disabled) + return; + LANG_FOR_EACH_INPUT_STATEMENT (file) { asection *sect; diff --git a/ld/ldlex.h b/ld/ldlex.h index 999d0defc61..1e20abbe122 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -171,6 +171,8 @@ enum option_values OPTION_CTF_VARIABLES, OPTION_NO_CTF_VARIABLES, OPTION_CTF_SHARE_TYPES, + OPTION_DISABLE_CTF_DEDUP, + OPTION_ENABLE_CTF_DEDUP, OPTION_ERROR_EXECSTACK, OPTION_NO_ERROR_EXECSTACK, OPTION_WARN_EXECSTACK_OBJECTS, diff --git a/ld/lexsup.c b/ld/lexsup.c index 7de6e257ad0..112cc8e7c35 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -650,6 +650,11 @@ static const struct ld_option ld_options[] = " is: share-unconflicted (default),\n" " share-duplicated"), TWO_DASHES }, + { {"disable-ctf-dedup", no_argument, NULL, OPTION_DISABLE_CTF_DEDUP}, + '\0', NULL, N_("Disable CTF and BTF deduplication: just concatenate\n"), + TWO_DASHES }, + { {"enable-ctf-dedup", no_argument, NULL, OPTION_ENABLE_CTF_DEDUP}, + '\0', NULL, NULL, NO_HELP } }; #define OPTION_COUNT ARRAY_SIZE (ld_options) @@ -1858,6 +1863,14 @@ parse_args (unsigned argc, char **argv) else fatal (_("%P: bad --ctf-share-types option: %s\n"), optarg); break; + + case OPTION_DISABLE_CTF_DEDUP: + link_info.ctf_disabled = true; + break; + + case OPTION_ENABLE_CTF_DEDUP: + link_info.ctf_disabled = false; + break; } }