[PATCH 08/11] alpha: reject an IFUNC address in read-only data in a static link

Matt Turner mattst88@gmail.com
Tue Sep 1 02:33:15 GMT 2026


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.
---
 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(-)
 create mode 100644 ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d
 create mode 100644 ld/testsuite/ld-alpha/ifunc-rodata-static.d
 create mode 100644 ld/testsuite/ld-alpha/ifunc-rodata-ztext.d
 create mode 100644 ld/testsuite/ld-alpha/ifunc-rodata.s

diff --git ./bfd/elf64-alpha.c ./bfd/elf64-alpha.c
index 470a6818023..687f4134d0e 100644
--- ./bfd/elf64-alpha.c
+++ ./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 ./ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d ./ld/testsuite/ld-alpha/ifunc-rodata-dynamic.d
new file mode 100644
index 00000000000..f796afebca7
--- /dev/null
+++ ./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 ./ld/testsuite/ld-alpha/ifunc-rodata-static.d ./ld/testsuite/ld-alpha/ifunc-rodata-static.d
new file mode 100644
index 00000000000..44fd3276218
--- /dev/null
+++ ./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 ./ld/testsuite/ld-alpha/ifunc-rodata-ztext.d ./ld/testsuite/ld-alpha/ifunc-rodata-ztext.d
new file mode 100644
index 00000000000..c58d7e3536d
--- /dev/null
+++ ./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 ./ld/testsuite/ld-alpha/ifunc-rodata.s ./ld/testsuite/ld-alpha/ifunc-rodata.s
new file mode 100644
index 00000000000..f900cb8004d
--- /dev/null
+++ ./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
-- 
2.54.0



More information about the Binutils mailing list