PR 33593 Misplaced synthetic plt symbols in aarch64 PIE binaries
Alan Modra
amodra@gmail.com
Wed Feb 4 22:12:42 GMT 2026
On Tue, Feb 03, 2026 at 06:21:59PM +0100, Michael Matz wrote:
> Hello,
>
> On Sat, 31 Jan 2026, Alan Modra wrote:
>
> > On Sat, Jan 31, 2026 at 12:04:16PM +0100, Andreas Schwab wrote:
> > > https://inbox.sourceware.org/binutils/6f335280-099c-40d7-9391-27fa47e6e55e@suse.de/
> > > has an alternative patch.
> >
> > That one looks fine to me and simpler too. It would have been nice if
> > someone had reviewed it and had it commited, or put the patch url in
> > the bug, or assigned the bug.
>
> Ah, I sent it about the time I was going for (a long) vacation and didn't
> have time to investigate how to write a proper testcase for this. And
> then it vanished from my mind, sorry :-/ I still don't have a testcase,
> so I guess let's go with your patch.
OK, this is what I'm about to commit.
===
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 <matz@suse.de>
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)
--
Alan Modra
More information about the Binutils
mailing list