aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2025-04-25 21:28:25 +0100
committerNick Alcock <nick.alcock@oracle.com>2025-04-25 21:32:35 +0100
commit1cea8a8ce757eb5e99f228abdf73cd62578b7745 (patch)
tree9c04db3f0f90ba21ec4000e4ff4a87577b3f16ea
parent1ec572d423672c5fa9f2d214c4dee81f26b4d1dc (diff)
downloadbinutils-1cea8a8ce757eb5e99f228abdf73cd62578b7745.zip
binutils-1cea8a8ce757eb5e99f228abdf73cd62578b7745.tar.gz
binutils-1cea8a8ce757eb5e99f228abdf73cd62578b7745.tar.bz2
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.)
-rw-r--r--bfd/elf-bfd.h26
-rw-r--r--bfd/elf.c28
-rw-r--r--bfd/elflink.c20
-rw-r--r--include/bfdlink.h3
-rw-r--r--ld/ld.texi10
-rw-r--r--ld/ldlang.c12
-rw-r--r--ld/ldlex.h2
-rw-r--r--ld/lexsup.c13
8 files changed, 91 insertions, 23 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index d2bf8e5..0dde5dd 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 3f8bc83..768de17 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 0df1976..516a9e0 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 3d4d71b..bb1c651 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 6d51ccb..bc2155c 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 011c526..a714be7 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 999d0de..1e20abb 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 7de6e25..112cc8e 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -650,6 +650,11 @@ static const struct ld_option ld_options[] =
" <method> 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;
}
}