diff --git a/binutils-aarch64-big-bti-programs.patch b/binutils-aarch64-big-bti-programs.patch new file mode 100644 index 0000000..b9e50bd --- /dev/null +++ b/binutils-aarch64-big-bti-programs.patch @@ -0,0 +1,139 @@ +diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c +index 4592bd6da27..4faf642b422 100644 +--- a/bfd/elfnn-aarch64.c ++++ b/bfd/elfnn-aarch64.c +@@ -3675,7 +3675,7 @@ group_sections (struct elf_aarch64_link_hash_table *htab, + /* True if the inserted stub does not break BTI compatibility. */ + + static bool +-aarch64_bti_stub_p (bfd *input_bfd, ++aarch64_bti_stub_p (struct bfd_link_info *info, + struct elf_aarch64_stub_hash_entry *stub_entry) + { + /* Stubs without indirect branch are BTI compatible. */ +@@ -3685,12 +3685,22 @@ aarch64_bti_stub_p (bfd *input_bfd, + + /* Return true if the target instruction is compatible with BR x16. */ + ++ struct elf_aarch64_link_hash_table *globals = elf_aarch64_hash_table (info); + asection *section = stub_entry->target_section; + bfd_byte loc[4]; + file_ptr off = stub_entry->target_value; + bfd_size_type count = sizeof (loc); + +- if (!bfd_get_section_contents (input_bfd, section, loc, off, count)) ++ /* PLT code is not generated yet, so treat it specially. ++ Note: Checking elf_aarch64_obj_tdata.plt_type & PLT_BTI is not ++ enough because it only implies BTI in the PLT0 and tlsdesc PLT ++ entries. Normal PLT entries don't have BTI in a shared library ++ (because such PLT is normally not called indirectly and adding ++ the BTI when a stub targets a PLT would change the PLT layout ++ and it's too late for that here). */ ++ if (section == globals->root.splt) ++ memcpy (loc, globals->plt_entry, count); ++ else if (!bfd_get_section_contents (section->owner, section, loc, off, count)) + return false; + + uint32_t insn = bfd_getl32 (loc); +@@ -4637,11 +4647,24 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + + /* A stub with indirect jump may break BTI compatibility, so + insert another stub with direct jump near the target then. */ +- if (need_bti && !aarch64_bti_stub_p (input_bfd, stub_entry)) ++ if (need_bti && !aarch64_bti_stub_p (info, stub_entry)) + { ++ id_sec_bti = htab->stub_group[sym_sec->id].link_sec; ++ ++ /* If the stub with indirect jump and the BTI stub are in ++ the same stub group: change the indirect jump stub into ++ a BTI stub since a direct branch can reach the target. ++ The BTI landing pad is still needed in case another ++ stub indirectly jumps to it. */ ++ if (id_sec_bti == id_sec) ++ { ++ stub_entry->stub_type = aarch64_stub_bti_direct_branch; ++ goto skip_double_stub; ++ } ++ + stub_entry->double_stub = true; + htab->has_double_stub = true; +- id_sec_bti = htab->stub_group[sym_sec->id].link_sec; ++ + stub_name_bti = + elfNN_aarch64_stub_name (id_sec_bti, sym_sec, hash, irela); + if (!stub_name_bti) +@@ -4653,33 +4676,41 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + stub_entry_bti = + aarch64_stub_hash_lookup (&htab->stub_hash_table, + stub_name_bti, false, false); +- if (stub_entry_bti == NULL) +- stub_entry_bti = +- _bfd_aarch64_add_stub_entry_in_group (stub_name_bti, +- sym_sec, htab); +- if (stub_entry_bti == NULL) ++ if (stub_entry_bti != NULL) ++ BFD_ASSERT (stub_entry_bti->stub_type ++ == aarch64_stub_bti_direct_branch); ++ else + { +- free (stub_name); +- free (stub_name_bti); +- goto error_ret_free_internal; +- } +- +- stub_entry_bti->target_value = sym_value + irela->r_addend; +- stub_entry_bti->target_section = sym_sec; +- stub_entry_bti->stub_type = aarch64_stub_bti_direct_branch; +- stub_entry_bti->h = hash; +- stub_entry_bti->st_type = st_type; ++ stub_entry_bti = ++ _bfd_aarch64_add_stub_entry_in_group (stub_name_bti, ++ sym_sec, htab); ++ if (stub_entry_bti == NULL) ++ { ++ free (stub_name); ++ free (stub_name_bti); ++ goto error_ret_free_internal; ++ } + +- len = sizeof (BTI_STUB_ENTRY_NAME) + strlen (sym_name); +- stub_entry_bti->output_name = bfd_alloc (htab->stub_bfd, len); +- if (stub_entry_bti->output_name == NULL) +- { +- free (stub_name); +- free (stub_name_bti); +- goto error_ret_free_internal; ++ stub_entry_bti->target_value = ++ sym_value + irela->r_addend; ++ stub_entry_bti->target_section = sym_sec; ++ stub_entry_bti->stub_type = ++ aarch64_stub_bti_direct_branch; ++ stub_entry_bti->h = hash; ++ stub_entry_bti->st_type = st_type; ++ ++ len = sizeof (BTI_STUB_ENTRY_NAME) + strlen (sym_name); ++ stub_entry_bti->output_name = bfd_alloc (htab->stub_bfd, ++ len); ++ if (stub_entry_bti->output_name == NULL) ++ { ++ free (stub_name); ++ free (stub_name_bti); ++ goto error_ret_free_internal; ++ } ++ snprintf (stub_entry_bti->output_name, len, ++ BTI_STUB_ENTRY_NAME, sym_name); + } +- snprintf (stub_entry_bti->output_name, len, +- BTI_STUB_ENTRY_NAME, sym_name); + + /* Update the indirect call stub to target the BTI stub. */ + stub_entry->target_value = 0; +@@ -4688,7 +4719,7 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd, + stub_entry->h = NULL; + stub_entry->st_type = STT_FUNC; + } +- ++skip_double_stub: + *stub_changed = true; + } + diff --git a/binutils.spec b/binutils.spec index f8f8ae3..36a86fd 100644 --- a/binutils.spec +++ b/binutils.spec @@ -2,7 +2,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?_with_debug:-debug} Version: 2.41 -Release: 11%{?dist} +Release: 12%{?dist} License: GPL-3.0-or-later AND (GPL-3.0-or-later WITH Bison-exception-2.2) AND (LGPL-2.0-or-later WITH GCC-exception-2.0) AND BSD-3-Clause AND GFDL-1.3-or-later AND GPL-2.0-or-later LGPL-2.1-or-later AND LGPL-2.0-or-later URL: https://sourceware.org/binutils @@ -282,6 +282,10 @@ Patch22: binutils-x86-64-v3.patch # Lifetime: Fixed in 2.42 Patch23: binutils-big-merge.patch +# Purpose: Fix linker generated call veneers for large AArch64 programs with BTI enabled. +# Lifetime: Fixed in 2.42 +Patch24: binutils-aarch64-big-bti-programs.patch + #---------------------------------------------------------------------------- Provides: bundled(libiberty) @@ -1287,6 +1291,9 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Tue Nov 07 2023 Nick Clifton - 2.41-12 +- Fix the bfd linker's generation of call stubs for large AArch64 binaries with BTI enabled. (#2241902) + * Tue Nov 07 2023 Nick Clifton - 2.41-11 - Fix merging strings when linking really big programs.