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

Matt Turner <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.