[PATCH 1/3] RISC-V: Allow to generate RELATIVE in got if pie and sections of GOT_HO20 are all discared
Nelson Chu
nelson@rivosinc.com
Sat Jun 7 08:36:39 GMT 2025
This happened when I was porting the relr stuff, and caused problem for
relr-discard testcases. Considering there is an got entry needs an dynamic
RELATIVE relocation when pie, we used to have an assert to make sure that the
h->got.offset was marked as done in the relocate_section function. But if the
sections of related GOT_HO20 are all discared by linker script, all related
GOT_HI20 will be skipped and converted to R_RISCV_NONE in the relocate_section,
so that the h->got.offset won't be marked as done, and then break the link.
According to the relr-discard testcases of aarch64 and loongarch, it seems
still need to generate a dynamic RELATIVE for this case. The loongarch seems
doesn't have the assert, but aarch64 and x86 have. I don't know how it works
with the assert check for this case, so I just ignore the assert until someone
clarify and figure it out.
---
bfd/elfnn-riscv.c | 17 ++++-
ld/testsuite/ld-riscv-elf/discard-pic.d | 15 +++++
ld/testsuite/ld-riscv-elf/discard-pie.d | 15 +++++
ld/testsuite/ld-riscv-elf/discard.ld | 13 ++++
ld/testsuite/ld-riscv-elf/discard.s | 75 ++++++++++++++++++++++
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 3 +
6 files changed, 135 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-riscv-elf/discard-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/discard-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/discard.ld
create mode 100644 ld/testsuite/ld-riscv-elf/discard.s
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 1c494f5f986..db9372c2b10 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3446,9 +3446,20 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
/* If this is a local symbol reference, we just want to emit
a RELATIVE reloc. This can happen if it is a -Bsymbolic link,
or a pie link, or the symbol was forced to be local because
- of a version file. The entry in the global offset table will
- already have been initialized in the relocate_section function. */
- BFD_ASSERT ((h->got.offset & 1) != 0);
+ of a version file. The entry in the global offset table "should"
+ already have been initialized in the relocate_section function,
+ except the sections of the related relocation are all discarded. */
+
+ /* If the sections of the related relocation are all discarded, then
+ the RELOC_AGAINST_DISCARDED_SECTION cleans all related relocation
+ to R_RISCV_NONE in the relocate_section, so the h->got.offset will
+ not be marked as done in the relocate_section function. In this
+ case most of the targets seems still generate a RELATIVE reloc,
+ but I don't know how that works with the following assert, so just
+ ignore it until someone clarify and figure this out.
+
+ BFD_ASSERT ((h->got.offset & 1) != 0); */
+
asection *sec = h->root.u.def.section;
rela.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
rela.r_addend = (h->root.u.def.value
diff --git a/ld/testsuite/ld-riscv-elf/discard-pic.d b/ld/testsuite/ld-riscv-elf/discard-pic.d
new file mode 100644
index 00000000000..f876cdf06ba
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/discard-pic.d
@@ -0,0 +1,15 @@
+#source: discard.s
+#as: -march=rv64i -mabi=lp64
+#ld: -shared -T discard.ld -melf64lriscv
+#readelf: -rW
+
+Relocation section '\.rela\.dyn'.*
+[ ]+Offset[ ]+Info[ ]+Type.*
+0000000000020010[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10004
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0000000000020018[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000001000c[ ]+sym_global \+ 0
+0000000000020020[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000001000c[ ]+sym_global_keep \+ 0
diff --git a/ld/testsuite/ld-riscv-elf/discard-pie.d b/ld/testsuite/ld-riscv-elf/discard-pie.d
new file mode 100644
index 00000000000..4e0d8cfb495
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/discard-pie.d
@@ -0,0 +1,15 @@
+#source: discard.s
+#as: -march=rv64i -mabi=lp64
+#ld: -pie -T discard.ld -melf64lriscv
+#readelf: -rW
+
+Relocation section '\.rela\.dyn'.*
+[ ]+Offset[ ]+Info[ ]+Type.*
+0000000000020010[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10004
+0000000000020018[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+1000c
+0000000000020020[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+1000c
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
+0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
diff --git a/ld/testsuite/ld-riscv-elf/discard.ld b/ld/testsuite/ld-riscv-elf/discard.ld
new file mode 100644
index 00000000000..3afed216fbc
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/discard.ld
@@ -0,0 +1,13 @@
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+SECTIONS
+{
+ /DISCARD/ : { *(.discard.*) }
+
+ . = 0x10000;
+ .text : { *(.text) }
+ . = 0x20000;
+ .got : { *(.got) *(.got.plt)}
+ . = 0x30000;
+ .data : { *(.data) *(.data.*) }
+}
diff --git a/ld/testsuite/ld-riscv-elf/discard.s b/ld/testsuite/ld-riscv-elf/discard.s
new file mode 100644
index 00000000000..729a5f9995a
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/discard.s
@@ -0,0 +1,75 @@
+.text
+.option pic
+.p2align 3
+.global _start
+_start:
+ nop
+
+sym_local:
+sym_local_keep:
+ nop
+
+.global sym_hidden
+.hidden sym_hidden
+sym_hidden:
+ nop
+
+.global sym_global
+.global sym_global_keep
+sym_global:
+sym_global_keep:
+ nop
+
+.global sym_global_abs
+.set sym_global_abs, 42
+
+.global sym_weak_undef
+.weak sym_weak_undef
+
+.section .got_local_keep,"ax"
+ la x1, sym_local_keep
+.section .discard.got_local_keep,"ax"
+ la x1, sym_local_keep
+
+.section .got_global_keep,"ax"
+ la x1, sym_global_keep
+.section .discard.got_global_keep,"ax"
+ la x1, sym_global_keep
+
+# All relocation refer to sym_local are discarded.
+.section .discard.got_local,"ax"
+ la x1, sym_local
+
+# All relocation refer to sym_global are discarded.
+.section .discard.got_global,"ax"
+ la x1, sym_global
+
+.section .discard.local,"a"
+.p2align 1
+discard_local:
+.quad sym_local
+
+.section .discard.hidden,"a"
+.p2align 1
+discard_hidden:
+.quad sym_hidden
+
+.section .discard.global,"a"
+.p2align 1
+discard_global:
+.quad sym_global
+
+.section .discard.global_abs,"a"
+.p2align 1
+discard_global_abs:
+.quad sym_global_abs
+
+.section .discard.weak_undef,"a"
+.p2align 1
+discard_weak_undef:
+.quad sym_weak_undef
+
+.section .discard._DYNAMIC,"a"
+.p2align 1
+discard_DYNAMIC:
+.quad _DYNAMIC
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 9cb847d3d8a..d68a9145dcd 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -227,6 +227,9 @@ if [istarget "riscv*-*-*"] {
run_dump_test "data-reloc-rv64-addr32-pic"
run_dump_test "data-reloc-rv64-undef32-pic"
+ run_dump_test "discard-pie"
+ run_dump_test "discard-pic"
+
# IFUNC testcases.
# Check IFUNC by single type relocs.
run_dump_test_ifunc "ifunc-reloc-call-01" rv32 exe
--
2.39.5 (Apple Git-154)
More information about the Binutils
mailing list