From: Alan Modra Date: Wed, 4 Feb 2026 22:04:31 +0000 (+1030) Subject: PR 33593 Misplaced synthetic plt symbols in aarch64 PIE binaries X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2dfd38f93ce3b05d25c7bd14cbcff0fa3614c056;p=thirdparty%2Fbinutils-gdb.git PR 33593 Misplaced synthetic plt symbols in aarch64 PIE binaries elfNN_aarch64_plt_sym_val wrongly treats PIEs. PIEs are an executable but not ET_EXEC, instead being ET_DYN with DF_1_PIE set in DT_FLAGS_1 to distinguish them from shared libraries. get_plt_type scans .dynamic for DT_AARCH64_BTI_PLT and DT_AARCH64_PAC_PLT, setting PLT_BTI and PLT_PAC in the function return value respectively. It's easy enough to extend the .dynamic scan to also return DF_1_PIE in tdata is_pie. The patch also makes a few tidies, things I noticed when scanning all the code dealing with sw_protections.plt_type. PR 33593 * elfnn-aarch64.c (get_plt_type): Return DF_1_PIE via tdata is_pie. (elfNN_aarch64_plt_sym_val): Handle PIEs as well as ET_EXEC. (setup_plt_values): Delete wrong ET_EXEC comments. (elfNN_aarch64_late_size_sections): Remove excess parentheses. (elfNN_aarch64_finish_dynamic_sections): Rename type to plt_type, and simplify test for PLT_BTI or PLT_BTI_PAC. Co-Authored-By: Michael Matz --- diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 08077fb74f8..1ba7dd393e6 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -4979,7 +4979,6 @@ setup_plt_values (struct bfd_link_info *link_info, { globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry; - /* Only in ET_EXEC we need PLTn with BTI. */ if (bfd_link_executable (link_info)) { globals->plt_entry_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE; @@ -4997,7 +4996,6 @@ setup_plt_values (struct bfd_link_info *link_info, { globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry; - /* Only in ET_EXEC we need PLTn with BTI. */ if (bfd_link_executable (link_info)) { globals->plt_entry_size = PLT_BTI_SMALL_ENTRY_SIZE; @@ -9837,16 +9835,16 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, aarch64_plt_type plt_type = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type; - if ((plt_type == PLT_BTI_PAC) + if (plt_type == PLT_BTI_PAC && (!add_dynamic_entry (DT_AARCH64_BTI_PLT, 0) || !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0))) return false; - else if ((plt_type == PLT_BTI) + else if (plt_type == PLT_BTI && !add_dynamic_entry (DT_AARCH64_BTI_PLT, 0)) return false; - else if ((plt_type == PLT_PAC) + else if (plt_type == PLT_PAC && !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0)) return false; } @@ -10368,12 +10366,10 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, const bfd_byte *entry = elfNN_aarch64_tlsdesc_small_plt_entry; htab->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE; - aarch64_plt_type type + aarch64_plt_type plt_type = elf_aarch64_tdata (output_bfd)->sw_protections.plt_type; - if (type == PLT_BTI || type == PLT_BTI_PAC) - { - entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry; - } + if (plt_type & PLT_BTI) + entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry; memcpy (htab->root.splt->contents + htab->root.tlsdesc_plt, entry, htab->tlsdesc_plt_entry_size); @@ -10401,7 +10397,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, /* First instruction in BTI enabled PLT stub is a BTI instruction so skip it. */ - if (type & PLT_BTI) + if (plt_type & PLT_BTI) { plt_entry = plt_entry + 4; adrp1_addr = adrp1_addr + 4; @@ -10487,7 +10483,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, } /* Check if BTI-enabled (and/or PAC-enabled) PLTs are needed. - Returns the type needed. */ + Returns the type needed, and whether DF_1_PIE is set via tdata is_pie. */ static aarch64_plt_type get_plt_type (bfd *abfd) { @@ -10506,13 +10502,12 @@ get_plt_type (bfd *abfd) Elf_Internal_Dyn dyn; bfd_elfNN_swap_dyn_in (abfd, extdyn, &dyn); - /* Let's check the processor specific dynamic array tags. */ - bfd_vma tag = dyn.d_tag; - if (tag < DT_LOPROC || tag > DT_HIPROC) - continue; - - switch (tag) + switch (dyn.d_tag) { + case DT_FLAGS_1: + elf_tdata (abfd)->is_pie = (dyn.d_un.d_val & DF_1_PIE) != 0; + break; + case DT_AARCH64_BTI_PLT: ret |= PLT_BTI; break; @@ -10555,14 +10550,18 @@ elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt, = elf_aarch64_tdata (plt->owner)->sw_protections.plt_type; if (plt_type == PLT_BTI_PAC) { - if (elf_elfheader (plt->owner)->e_type == ET_EXEC) + if (elf_elfheader (plt->owner)->e_type == ET_EXEC + || (elf_elfheader (plt->owner)->e_type == ET_DYN + && elf_tdata (plt->owner)->is_pie)) pltn_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE; else pltn_size = PLT_PAC_SMALL_ENTRY_SIZE; } else if (plt_type == PLT_BTI) { - if (elf_elfheader (plt->owner)->e_type == ET_EXEC) + if (elf_elfheader (plt->owner)->e_type == ET_EXEC + || (elf_elfheader (plt->owner)->e_type == ET_DYN + && elf_tdata (plt->owner)->is_pie)) pltn_size = PLT_BTI_SMALL_ENTRY_SIZE; } else if (plt_type == PLT_PAC)