[binutils-gdb] alpha: reject an IFUNC address in read-only data in a static link

Sam James sjames@sourceware.org
Sat Sep 5 08:35:14 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=28884fbb19262ef861cb883e7975eee2356a01f1

commit 28884fbb19262ef861cb883e7975eee2356a01f1
Author: Matt Turner <mattst88@gmail.com>
Date:   Mon Aug 31 22:33:15 2026 -0400

    alpha: reject an IFUNC address in read-only data in a static link
    
    The address of an IFUNC needs an R_ALPHA_IRELATIVE applied to the word
    that holds it. In a read-only section that means relocating a read-only
    page, which is DT_TEXTREL in a dynamic link but has nothing to do it in
    a static one: libc's startup code runs after the kernel has mapped the
    segment and cannot make it writable.
    
    Other targets hand out the address of a PLT stub in that case. Alpha has
    no PLT entry for a non-dynamic function, so report it instead.

Diff:
---
 bfd/elf64-alpha.c                            | 25 ++++++++++++++++++++++++-
 ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d | 12 ++++++++++++
 ld/testsuite/ld-alpha/ifunc-rodata-static.d  |  3 +++
 ld/testsuite/ld-alpha/ifunc-rodata-ztext.d   |  4 ++++
 ld/testsuite/ld-alpha/ifunc-rodata.s         | 22 ++++++++++++++++++++++
 5 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 470a6818023..687f4134d0e 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -4901,7 +4901,30 @@ elf64_alpha_relocate_section (struct bfd_link_info *info,
 		dynaddend = value;
 
 		if (elf64_alpha_ifunc_irelplt_p (h, sym, info))
-		  srel_out = elf_hash_table (info)->irelplt;
+		  {
+		    srel_out = elf_hash_table (info)->irelplt;
+
+		    /* Startup code in a static executable applies this after
+		       the kernel has mapped the segment, and unlike the
+		       dynamic linker it cannot make a read-only one writable.
+		       Other targets hand out the address of a PLT stub
+		       instead; alpha has no PLT entry for a non-dynamic
+		       function.  */
+		    if ((input_section->flags & SEC_READONLY) != 0
+			&& !elf_hash_table (info)->dynamic_sections_created)
+		      {
+			_bfd_error_handler
+			  /* xgettext:c-format */
+			  (_("%pB: address of STT_GNU_IFUNC symbol `%s' in "
+			     "read-only section `%pA' cannot be relocated in "
+			     "a static link"),
+			   input_bfd,
+			   elf64_alpha_sym_name (input_bfd, symtab_hdr, h,
+						 sym, sec),
+			   input_section);
+			ret_val = false;
+		      }
+		  }
 	      }
 	    else if (bfd_link_pic (info)
 		     && r_symndx != STN_UNDEF
diff --git a/ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d b/ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d
new file mode 100644
index 00000000000..f796afebca7
--- /dev/null
+++ b/ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d
@@ -0,0 +1,12 @@
+#source: ifunc-rodata.s
+#ld: -melf64alpha -z notext tmpdir/libalphaifunc.so
+#readelf: -Wrd
+
+#...
+ +0x0+16 +\(TEXTREL\) +0x0
+#...
+Relocation section '\.rela\.dyn' .* contains 2 entries:
+#...
+[0-9a-f]+ +[0-9a-f]+ +R_ALPHA_IRELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_ALPHA_IRELATIVE +[0-9a-f]+
+#pass
diff --git a/ld/testsuite/ld-alpha/ifunc-rodata-static.d b/ld/testsuite/ld-alpha/ifunc-rodata-static.d
new file mode 100644
index 00000000000..44fd3276218
--- /dev/null
+++ b/ld/testsuite/ld-alpha/ifunc-rodata-static.d
@@ -0,0 +1,3 @@
+#source: ifunc-rodata.s
+#ld: -melf64alpha
+#error: \A[^\n]*: address of STT_GNU_IFUNC symbol `global_ifunc' in read-only section `\.rodata' cannot be relocated in a static link\n[^\n]*: address of STT_GNU_IFUNC symbol `local_ifunc' in read-only section `\.rodata' cannot be relocated in a static link\n[^\n]*: final link failed[^\n]*\n?\Z
diff --git a/ld/testsuite/ld-alpha/ifunc-rodata-ztext.d b/ld/testsuite/ld-alpha/ifunc-rodata-ztext.d
new file mode 100644
index 00000000000..c58d7e3536d
--- /dev/null
+++ b/ld/testsuite/ld-alpha/ifunc-rodata-ztext.d
@@ -0,0 +1,4 @@
+#source: ifunc-rodata.s
+#ld: -melf64alpha -z text tmpdir/libalphaifunc.so
+#readelf: -Wr
+#error: \A[^\n]*: read-only segment has dynamic relocations\n?\Z
diff --git a/ld/testsuite/ld-alpha/ifunc-rodata.s b/ld/testsuite/ld-alpha/ifunc-rodata.s
new file mode 100644
index 00000000000..f900cb8004d
--- /dev/null
+++ b/ld/testsuite/ld-alpha/ifunc-rodata.s
@@ -0,0 +1,22 @@
+	.text
+
+	.globl	global_ifunc
+	.type	global_ifunc, @gnu_indirect_function
+global_ifunc:
+	ret
+
+	.type	local_ifunc, @gnu_indirect_function
+local_ifunc:
+	ret
+
+	.globl	_start
+	.ent	_start
+_start:
+	ret
+	.end	_start
+
+	# The IRELATIVE for each of these is applied to a read-only page:
+	# DT_TEXTREL in a dynamic link, an error in a static one.
+	.section .rodata,"a",@progbits
+	.quad	global_ifunc
+	.quad	local_ifunc


More information about the Binutils-cvs mailing list