[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
Mon Jun 23 15:46:06 GMT 2025


Umm, I probably found the root cause, so the workaround in this patch
should be wrong.  I will send another patch for this issue later after
passing some regressions.

Thanks
Nelson

On Fri, Jun 20, 2025 at 1:28 PM Nelson Chu <nelson@rivosinc.com> wrote:

> Hi guys,
>
> I plan to commit this one, and the latter one "RISC-V: Don't allocate
> dynamic relocation if it's section was discarded", if there are no
> objections until next weekend ;)
>
> Thanks
> Nelson
>
> On Sat, Jun 7, 2025 at 4:36 PM Nelson Chu <nelson@rivosinc.com> wrote:
>
>> 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)
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/binutils/attachments/20250623/298cfd34/attachment.htm>


More information about the Binutils mailing list