[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