[2/3] RISC-V: Clarify link behaviors of R_RISCV_32/64 relocations with ABS symbol.

Message ID 20230325004113.22673-2-nelson@rivosinc.com
State Accepted
Headers
Series [1/3] RISC-V: Extract the ld code which are too complicated, and may be reused. |

Checks

Context Check Description
snail/binutils-gdb-check success Github commit url

Commit Message

Nelson Chu March 25, 2023, 12:41 a.m. UTC
  There are two improvements, which are all referenced to aarch64,

* R_RISCV_32 with non ABS symbol cannot be used under RV64 when making
  shard objects.

* Don't need dynamic relocation for R_RISCV_32/64 under RV32/RV64 when
  making shared objects, if the referenced symbol is local ABS symbol.

However, considering this link,
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/341

Seems like we should makes all R_RISCV_32/64 relocs with ABS symbol
that don't need any dynamic relocations when making the shared objects.
But anyway, I just sync the current behavior as aarch64 ld, in case
there are any unexpected behaviors happen.

Passed the gcc/binutils regressions in riscv-gnu-toolchain.

bfd/
    * elfnn-riscv.c (riscv_elf_check_relocs): Only allow R_RISCV_32 with ABS
    symbol under RV64.
    (riscv_elf_relocate_section): R_RISCV_32/64 with local ABS symbol under
    RV32/RV64 doesn't need any dynamic relocation when making shared objects.
    I just make the implementations similar to other targets, so that will be
    more easy to mainatain.
ld/
    * testsuite/ld-riscv-elf/data-reloc*: New testcases.
    * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Added new data-reloc* testcases,
    and need to make ifunc-seperate* testcases work for rv32.
    * testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s: Likewise.
    * testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s: Likewise.
---
 bfd/elfnn-riscv.c                             | 61 ++++++++++++++++---
 .../ld-riscv-elf/data-reloc-rv32-pic.d        | 21 +++++++
 .../ld-riscv-elf/data-reloc-rv32-pie.d        | 18 ++++++
 .../ld-riscv-elf/data-reloc-rv32-symbolic.d   | 21 +++++++
 .../ld-riscv-elf/data-reloc-rv64-abs32-pic.d  | 13 ++++
 .../ld-riscv-elf/data-reloc-rv64-addr32-pic.d |  4 ++
 .../ld-riscv-elf/data-reloc-rv64-pic.d        | 21 +++++++
 .../ld-riscv-elf/data-reloc-rv64-pie.d        | 21 +++++++
 .../ld-riscv-elf/data-reloc-rv64-symbolic.d   | 21 +++++++
 .../data-reloc-rv64-undef32-pic.d             |  4 ++
 ld/testsuite/ld-riscv-elf/data-reloc.s        | 22 +++++++
 .../ifunc-seperate-caller-nonplt.s            |  2 +-
 .../ld-riscv-elf/ifunc-seperate-caller-plt.s  |  2 +-
 ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp    | 15 +++++
 14 files changed, 236 insertions(+), 10 deletions(-)
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d
 create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc.s
  

Comments

Nelson Chu March 30, 2023, 12:12 a.m. UTC | #1
At least passed the regressions of riscv-gnu-toolchain for this series
of patches, so committed them since they should be the correct way to
go.  The series of patches are listed as follows,
* RISC-V: Extract the ld code which are too complicated, and may be reused.
* RISC-V: Clarify link behaviors of R_RISCV_32/64 relocations with ABS symbol.
* RISC-V: PR28789, Reject R_RISCV_PCREL relocations with ABS symbol in PIC/PIE.

Thanks
Nelson

On Sat, Mar 25, 2023 at 8:41 AM Nelson Chu <nelson@rivosinc.com> wrote:
>
> There are two improvements, which are all referenced to aarch64,
>
> * R_RISCV_32 with non ABS symbol cannot be used under RV64 when making
>   shard objects.
>
> * Don't need dynamic relocation for R_RISCV_32/64 under RV32/RV64 when
>   making shared objects, if the referenced symbol is local ABS symbol.
>
> However, considering this link,
> https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/341
>
> Seems like we should makes all R_RISCV_32/64 relocs with ABS symbol
> that don't need any dynamic relocations when making the shared objects.
> But anyway, I just sync the current behavior as aarch64 ld, in case
> there are any unexpected behaviors happen.
>
> Passed the gcc/binutils regressions in riscv-gnu-toolchain.
>
> bfd/
>     * elfnn-riscv.c (riscv_elf_check_relocs): Only allow R_RISCV_32 with ABS
>     symbol under RV64.
>     (riscv_elf_relocate_section): R_RISCV_32/64 with local ABS symbol under
>     RV32/RV64 doesn't need any dynamic relocation when making shared objects.
>     I just make the implementations similar to other targets, so that will be
>     more easy to mainatain.
> ld/
>     * testsuite/ld-riscv-elf/data-reloc*: New testcases.
>     * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Added new data-reloc* testcases,
>     and need to make ifunc-seperate* testcases work for rv32.
>     * testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s: Likewise.
>     * testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s: Likewise.
> ---
>  bfd/elfnn-riscv.c                             | 61 ++++++++++++++++---
>  .../ld-riscv-elf/data-reloc-rv32-pic.d        | 21 +++++++
>  .../ld-riscv-elf/data-reloc-rv32-pie.d        | 18 ++++++
>  .../ld-riscv-elf/data-reloc-rv32-symbolic.d   | 21 +++++++
>  .../ld-riscv-elf/data-reloc-rv64-abs32-pic.d  | 13 ++++
>  .../ld-riscv-elf/data-reloc-rv64-addr32-pic.d |  4 ++
>  .../ld-riscv-elf/data-reloc-rv64-pic.d        | 21 +++++++
>  .../ld-riscv-elf/data-reloc-rv64-pie.d        | 21 +++++++
>  .../ld-riscv-elf/data-reloc-rv64-symbolic.d   | 21 +++++++
>  .../data-reloc-rv64-undef32-pic.d             |  4 ++
>  ld/testsuite/ld-riscv-elf/data-reloc.s        | 22 +++++++
>  .../ifunc-seperate-caller-nonplt.s            |  2 +-
>  .../ld-riscv-elf/ifunc-seperate-caller-plt.s  |  2 +-
>  ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp    | 15 +++++
>  14 files changed, 236 insertions(+), 10 deletions(-)
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d
>  create mode 100644 ld/testsuite/ld-riscv-elf/data-reloc.s
>
> diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
> index 59e949a2cb5..00f034a6751 100644
> --- a/bfd/elfnn-riscv.c
> +++ b/bfd/elfnn-riscv.c
> @@ -734,6 +734,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>        unsigned int r_type;
>        unsigned int r_symndx;
>        struct elf_link_hash_entry *h;
> +      bool is_abs_symbol = false;
>
>        r_symndx = ELFNN_R_SYM (rel->r_info);
>        r_type = ELFNN_R_TYPE (rel->r_info);
> @@ -753,6 +754,8 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>           if (isym == NULL)
>             return false;
>
> +         is_abs_symbol = isym->st_shndx == SHN_ABS ? true : false;
> +
>           /* Check relocation against local STT_GNU_IFUNC symbol.  */
>           if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
>             {
> @@ -778,6 +781,8 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>           while (h->root.type == bfd_link_hash_indirect
>                  || h->root.type == bfd_link_hash_warning)
>             h = (struct elf_link_hash_entry *) h->root.u.i.link;
> +
> +         is_abs_symbol = bfd_is_abs_symbol (&h->root) ? true : false;
>         }
>
>        if (h != NULL)
> @@ -879,13 +884,31 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>         case R_RISCV_HI20:
>           if (bfd_link_pic (info))
>             return bad_static_reloc (abfd, r_type, h);
> -         /* Fall through.  */
> +         goto static_reloc;
> +
> +       case R_RISCV_32:
> +         if (ARCH_SIZE > 32
> +             && bfd_link_pic (info)
> +             && (sec->flags & SEC_ALLOC) != 0)
> +           {
> +             if (is_abs_symbol)
> +               break;
> +
> +             reloc_howto_type *r_t = riscv_elf_rtype_to_howto (abfd, r_type);
> +             _bfd_error_handler
> +               (_("%pB: relocation %s against non-absolute symbol `%s' can "
> +                  "not be used in RVNN when making a shared object"),
> +                abfd, r_t ? r_t->name : _("<unknown>"),
> +                h != NULL ? h->root.root.string : "a local symbol");
> +             bfd_set_error (bfd_error_bad_value);
> +             return false;
> +           }
> +         goto static_reloc;
>
>         case R_RISCV_COPY:
>         case R_RISCV_JUMP_SLOT:
>         case R_RISCV_RELATIVE:
>         case R_RISCV_64:
> -       case R_RISCV_32:
>           /* Fall through.  */
>
>         static_reloc:
> @@ -2630,6 +2653,11 @@ riscv_elf_relocate_section (bfd *output_bfd,
>           break;
>
>         case R_RISCV_32:
> +         /* Non ABS symbol should be blocked in check_relocs.  */
> +         if (ARCH_SIZE > 32)
> +           break;
> +         /* Fall through.  */
> +
>         case R_RISCV_64:
>           if ((input_section->flags & SEC_ALLOC) == 0)
>             break;
> @@ -2639,7 +2667,6 @@ riscv_elf_relocate_section (bfd *output_bfd,
>             {
>               Elf_Internal_Rela outrel;
>               asection *sreloc;
> -             bool skip_static_relocation, skip_dynamic_relocation;
>
>               /* When generating a shared object, these relocations
>                  are copied into the output file to be resolved at run
> @@ -2648,26 +2675,44 @@ riscv_elf_relocate_section (bfd *output_bfd,
>               outrel.r_offset =
>                 _bfd_elf_section_offset (output_bfd, info, input_section,
>                                          rel->r_offset);
> -             skip_static_relocation = outrel.r_offset != (bfd_vma) -2;
> -             skip_dynamic_relocation = outrel.r_offset >= (bfd_vma) -2;
> +             bool skip = false;
> +             bool relocate = false;
> +             if (outrel.r_offset == (bfd_vma) -1)
> +               skip = true;
> +             else if (outrel.r_offset == (bfd_vma) -2)
> +               {
> +                 skip = true;
> +                 relocate = true;
> +               }
> +             else if (h != NULL && bfd_is_abs_symbol (&h->root))
> +               {
> +                 /* Don't need dynamic reloc when the ABS symbol is
> +                    non-dynamic or forced to local.  Maybe just use
> +                    SYMBOL_REFERENCES_LOCAL to check?  */
> +                 skip = (h->forced_local || (h->dynindx == -1));
> +                 relocate = skip;
> +               }
> +
>               outrel.r_offset += sec_addr (input_section);
>
> -             if (skip_dynamic_relocation)
> -               memset (&outrel, 0, sizeof outrel);
> +             if (skip)
> +               memset (&outrel, 0, sizeof outrel);     /* R_RISCV_NONE.  */
>               else if (RISCV_COPY_INPUT_RELOC (info, h))
>                 {
> +                 /* Maybe just use !SYMBOL_REFERENCES_LOCAL to check?  */
>                   outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
>                   outrel.r_addend = rel->r_addend;
>                 }
>               else
>                 {
> +                 /* This symbol is local, or marked to become local.  */
>                   outrel.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
>                   outrel.r_addend = relocation + rel->r_addend;
>                 }
>
>               sreloc = elf_section_data (input_section)->sreloc;
>               riscv_elf_append_rela (output_bfd, sreloc, &outrel);
> -             if (skip_static_relocation)
> +             if (!relocate)
>                 continue;
>             }
>           break;
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d
> new file mode 100644
> index 00000000000..13f34e052b7
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d
> @@ -0,0 +1,21 @@
> +#source: data-reloc.s
> +#as: -march=rv32i -mabi=ilp32 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
> +#ld: -m[riscv_choose_ilp32_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+8000 <addr_globl>:
> +    8000:      00000000                .word   0x00000000
> +                       8000: R_RISCV_32        addr_globl
> +
> +0+8004 <addr_local>:
> +       ...
> +                       8004: R_RISCV_RELATIVE  \*ABS\*\+0x8004
> +                       8008: R_RISCV_32        abs
> +    800c:      00000200                .word   0x00000200
> +    8010:      00000000                .word   0x00000000
> +                       8010: R_RISCV_32        undef
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d
> new file mode 100644
> index 00000000000..1e8f35a9c18
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d
> @@ -0,0 +1,18 @@
> +#source: data-reloc.s
> +#as: -march=rv32i -mabi=ilp32 -defsym __abs__=1 -defsym __addr__=1
> +#ld: -m[riscv_choose_ilp32_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -pie
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +Disassembly of section .text:
> +
> +0+8000 <addr_globl>:
> +    8000:      00000000                .word   0x00000000
> +                       8000: R_RISCV_RELATIVE  \*ABS\*\+0x8000
> +
> +0+8004 <addr_local>:
> +    8004:      00000000                .word   0x00000000
> +                       8004: R_RISCV_RELATIVE  \*ABS\*\+0x8004
> +    8008:      00000100                .word   0x00000100
> +    800c:      00000200                .word   0x00000200
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d
> new file mode 100644
> index 00000000000..5c947e2b93b
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d
> @@ -0,0 +1,21 @@
> +#source: data-reloc.s
> +#as: -march=rv32i -mabi=ilp32 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
> +#ld: -m[riscv_choose_ilp32_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared -Bsymbolic
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+8000 <addr_globl>:
> +    8000:      00000000                .word   0x00000000
> +                       8000: R_RISCV_RELATIVE  \*ABS\*\+0x8000
> +
> +0+8004 <addr_local>:
> +       ...
> +                       8004: R_RISCV_RELATIVE  \*ABS\*\+0x8004
> +                       8008: R_RISCV_RELATIVE  \*ABS\*\+0x100
> +    800c:      00000200                .word   0x00000200
> +    8010:      00000000                .word   0x00000000
> +                       8010: R_RISCV_32        undef
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d
> new file mode 100644
> index 00000000000..1d3686de353
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d
> @@ -0,0 +1,13 @@
> +#source: data-reloc.s
> +#as: -march=rv64i -mabi=lp64 -defsym __abs__=1
> +#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+8000 <.text>:
> +    8000:      00000100                .word   0x00000100
> +    8004:      00000200                .word   0x00000200
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d
> new file mode 100644
> index 00000000000..39b50e33044
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d
> @@ -0,0 +1,4 @@
> +#source: data-reloc.s
> +#as: -march=rv64i -mabi=lp64 -defsym __addr__=1
> +#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0  -shared
> +#error: .*relocation R_RISCV_32 against non-absolute symbol `addr_globl' can not be used in RV64 when making a shared object.*
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d
> new file mode 100644
> index 00000000000..dab0ccc9260
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d
> @@ -0,0 +1,21 @@
> +#source: data-reloc.s
> +#as: -march=rv64i -mabi=lp64 -defsym __64_bit__=1 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
> +#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+8000 <addr_globl>:
> +       ...
> +                       8000: R_RISCV_64        addr_globl
> +
> +0+8008 <addr_local>:
> +       ...
> +                       8008: R_RISCV_RELATIVE  \*ABS\*\+0x8008
> +                       8010: R_RISCV_64        abs
> +    8018:      00000200                .word   0x00000200
> +       ...
> +                       8020: R_RISCV_64        undef
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d
> new file mode 100644
> index 00000000000..fd6c470f680
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d
> @@ -0,0 +1,21 @@
> +#source: data-reloc.s
> +#as: -march=rv64i -mabi=lp64 -defsym __64_bit__=1 -defsym __abs__=1 -defsym __addr__=1
> +#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -pie
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+8000 <addr_globl>:
> +       ...
> +                       8000: R_RISCV_RELATIVE  \*ABS\*\+0x8000
> +
> +0+8008 <addr_local>:
> +       ...
> +                       8008: R_RISCV_RELATIVE  \*ABS\*\+0x8008
> +    8010:      00000100                .word   0x00000100
> +    8014:      00000000                .word   0x00000000
> +    8018:      00000200                .word   0x00000200
> +    801c:      00000000                .word   0x00000000
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d
> new file mode 100644
> index 00000000000..5d41f869b72
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d
> @@ -0,0 +1,21 @@
> +#source: data-reloc.s
> +#as: -march=rv64i -mabi=lp64 -defsym __64_bit__=1 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
> +#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared -Bsymbolic
> +#objdump: -dR
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+8000 <addr_globl>:
> +       ...
> +                       8000: R_RISCV_RELATIVE  \*ABS\*\+0x8000
> +
> +0+8008 <addr_local>:
> +       ...
> +                       8008: R_RISCV_RELATIVE  \*ABS\*\+0x8008
> +                       8010: R_RISCV_RELATIVE  \*ABS\*\+0x100
> +    8018:      00000200                .word   0x00000200
> +       ...
> +                       8020: R_RISCV_64        undef
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d
> new file mode 100644
> index 00000000000..e5de484142c
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d
> @@ -0,0 +1,4 @@
> +#source: data-reloc.s
> +#as: -march=rv64i -mabi=lp64 -defsym __undef__=1
> +#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0  -shared
> +#error: .*relocation R_RISCV_32 against non-absolute symbol `undef' can not be used in RV64 when making a shared object.*
> diff --git a/ld/testsuite/ld-riscv-elf/data-reloc.s b/ld/testsuite/ld-riscv-elf/data-reloc.s
> new file mode 100644
> index 00000000000..37151500f77
> --- /dev/null
> +++ b/ld/testsuite/ld-riscv-elf/data-reloc.s
> @@ -0,0 +1,22 @@
> +       .macro  DATA symbol
> +.ifdef __64_bit__
> +       .quad   \symbol
> +.else
> +       .word   \symbol
> +.endif
> +       .endm
> +.ifdef __addr__
> +       .globl  addr_globl
> +addr_globl:
> +       DATA    addr_globl
> +addr_local:
> +       DATA    addr_local
> +.endif
> +.ifdef __abs__
> +       .hidden abs_local
> +       DATA    abs
> +       DATA    abs_local
> +.endif
> +.ifdef __undef__
> +       DATA    undef
> +.endif
> diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s
> index 23c7254ad5b..df0d33b97e2 100644
> --- a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s
> +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s
> @@ -20,4 +20,4 @@ main:
>
>         .data
>  foo_addr:
> -       .long   foo
> +       .quad   foo
> diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s
> index 8aa64034706..cc1608a9803 100644
> --- a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s
> +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s
> @@ -23,4 +23,4 @@ main:
>
>         .data
>  foo_addr:
> -       .long   foo
> +       .quad   foo
> diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
> index 5dd6144efd3..1b2a5ce2cb2 100644
> --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
> +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
> @@ -217,6 +217,16 @@ if [istarget "riscv*-*-*"] {
>      run_dump_test "shared-lib-nopic-03"
>      run_dump_test "shared-lib-nopic-04"
>
> +    run_dump_test "data-reloc-rv64-pic"
> +    run_dump_test "data-reloc-rv64-pie"
> +    run_dump_test "data-reloc-rv64-symbolic"
> +    run_dump_test "data-reloc-rv32-pic"
> +    run_dump_test "data-reloc-rv32-pie"
> +    run_dump_test "data-reloc-rv32-symbolic"
> +    run_dump_test "data-reloc-rv64-abs32-pic"
> +    run_dump_test "data-reloc-rv64-addr32-pic"
> +    run_dump_test "data-reloc-rv64-undef32-pic"
> +
>      # IFUNC testcases.
>      # Check IFUNC by single type relocs.
>      run_dump_test_ifunc "ifunc-reloc-call-01" rv32 exe
> @@ -270,6 +280,11 @@ if [istarget "riscv*-*-*"] {
>      run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pie
>      run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pic
>
> +    # TODO: Make the following tests work under RV32.
> +    if [istarget "riscv32-*-*"] {
> +      return
> +    }
> +
>      # Setup shared libraries.
>      run_ld_link_tests {
>         { "Build shared library for IFUNC non-PLT caller"
> --
> 2.37.1 (Apple Git-137.1)
>
  

Patch

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 59e949a2cb5..00f034a6751 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -734,6 +734,7 @@  riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       unsigned int r_type;
       unsigned int r_symndx;
       struct elf_link_hash_entry *h;
+      bool is_abs_symbol = false;
 
       r_symndx = ELFNN_R_SYM (rel->r_info);
       r_type = ELFNN_R_TYPE (rel->r_info);
@@ -753,6 +754,8 @@  riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  if (isym == NULL)
 	    return false;
 
+	  is_abs_symbol = isym->st_shndx == SHN_ABS ? true : false;
+
 	  /* Check relocation against local STT_GNU_IFUNC symbol.  */
 	  if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
 	    {
@@ -778,6 +781,8 @@  riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  is_abs_symbol = bfd_is_abs_symbol (&h->root) ? true : false;
 	}
 
       if (h != NULL)
@@ -879,13 +884,31 @@  riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_RISCV_HI20:
 	  if (bfd_link_pic (info))
 	    return bad_static_reloc (abfd, r_type, h);
-	  /* Fall through.  */
+	  goto static_reloc;
+
+	case R_RISCV_32:
+	  if (ARCH_SIZE > 32
+	      && bfd_link_pic (info)
+	      && (sec->flags & SEC_ALLOC) != 0)
+	    {
+	      if (is_abs_symbol)
+		break;
+
+	      reloc_howto_type *r_t = riscv_elf_rtype_to_howto (abfd, r_type);
+	      _bfd_error_handler
+		(_("%pB: relocation %s against non-absolute symbol `%s' can "
+		   "not be used in RVNN when making a shared object"),
+		 abfd, r_t ? r_t->name : _("<unknown>"),
+		 h != NULL ? h->root.root.string : "a local symbol");
+	      bfd_set_error (bfd_error_bad_value);
+	      return false;
+	    }
+	  goto static_reloc;
 
 	case R_RISCV_COPY:
 	case R_RISCV_JUMP_SLOT:
 	case R_RISCV_RELATIVE:
 	case R_RISCV_64:
-	case R_RISCV_32:
 	  /* Fall through.  */
 
 	static_reloc:
@@ -2630,6 +2653,11 @@  riscv_elf_relocate_section (bfd *output_bfd,
 	  break;
 
 	case R_RISCV_32:
+	  /* Non ABS symbol should be blocked in check_relocs.  */
+	  if (ARCH_SIZE > 32)
+	    break;
+	  /* Fall through.  */
+
 	case R_RISCV_64:
 	  if ((input_section->flags & SEC_ALLOC) == 0)
 	    break;
@@ -2639,7 +2667,6 @@  riscv_elf_relocate_section (bfd *output_bfd,
 	    {
 	      Elf_Internal_Rela outrel;
 	      asection *sreloc;
-	      bool skip_static_relocation, skip_dynamic_relocation;
 
 	      /* When generating a shared object, these relocations
 		 are copied into the output file to be resolved at run
@@ -2648,26 +2675,44 @@  riscv_elf_relocate_section (bfd *output_bfd,
 	      outrel.r_offset =
 		_bfd_elf_section_offset (output_bfd, info, input_section,
 					 rel->r_offset);
-	      skip_static_relocation = outrel.r_offset != (bfd_vma) -2;
-	      skip_dynamic_relocation = outrel.r_offset >= (bfd_vma) -2;
+	      bool skip = false;
+	      bool relocate = false;
+	      if (outrel.r_offset == (bfd_vma) -1)
+		skip = true;
+	      else if (outrel.r_offset == (bfd_vma) -2)
+		{
+		  skip = true;
+		  relocate = true;
+		}
+	      else if (h != NULL && bfd_is_abs_symbol (&h->root))
+		{
+		  /* Don't need dynamic reloc when the ABS symbol is
+		     non-dynamic or forced to local.  Maybe just use
+		     SYMBOL_REFERENCES_LOCAL to check?  */
+		  skip = (h->forced_local || (h->dynindx == -1));
+		  relocate = skip;
+		}
+
 	      outrel.r_offset += sec_addr (input_section);
 
-	      if (skip_dynamic_relocation)
-		memset (&outrel, 0, sizeof outrel);
+	      if (skip)
+		memset (&outrel, 0, sizeof outrel);	/* R_RISCV_NONE.  */
 	      else if (RISCV_COPY_INPUT_RELOC (info, h))
 		{
+		  /* Maybe just use !SYMBOL_REFERENCES_LOCAL to check?  */
 		  outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
 		  outrel.r_addend = rel->r_addend;
 		}
 	      else
 		{
+		  /* This symbol is local, or marked to become local.  */
 		  outrel.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
 		  outrel.r_addend = relocation + rel->r_addend;
 		}
 
 	      sreloc = elf_section_data (input_section)->sreloc;
 	      riscv_elf_append_rela (output_bfd, sreloc, &outrel);
-	      if (skip_static_relocation)
+	      if (!relocate)
 		continue;
 	    }
 	  break;
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d
new file mode 100644
index 00000000000..13f34e052b7
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pic.d
@@ -0,0 +1,21 @@ 
+#source: data-reloc.s
+#as: -march=rv32i -mabi=ilp32 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
+#ld: -m[riscv_choose_ilp32_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+8000 <addr_globl>:
+    8000:	00000000          	.word	0x00000000
+			8000: R_RISCV_32	addr_globl
+
+0+8004 <addr_local>:
+	...
+			8004: R_RISCV_RELATIVE	\*ABS\*\+0x8004
+			8008: R_RISCV_32	abs
+    800c:	00000200          	.word	0x00000200
+    8010:	00000000          	.word	0x00000000
+			8010: R_RISCV_32	undef
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d
new file mode 100644
index 00000000000..1e8f35a9c18
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-pie.d
@@ -0,0 +1,18 @@ 
+#source: data-reloc.s
+#as: -march=rv32i -mabi=ilp32 -defsym __abs__=1 -defsym __addr__=1
+#ld: -m[riscv_choose_ilp32_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -pie
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+Disassembly of section .text:
+
+0+8000 <addr_globl>:
+    8000:	00000000          	.word	0x00000000
+			8000: R_RISCV_RELATIVE	\*ABS\*\+0x8000
+
+0+8004 <addr_local>:
+    8004:	00000000          	.word	0x00000000
+			8004: R_RISCV_RELATIVE	\*ABS\*\+0x8004
+    8008:	00000100          	.word	0x00000100
+    800c:	00000200          	.word	0x00000200
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d
new file mode 100644
index 00000000000..5c947e2b93b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv32-symbolic.d
@@ -0,0 +1,21 @@ 
+#source: data-reloc.s
+#as: -march=rv32i -mabi=ilp32 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
+#ld: -m[riscv_choose_ilp32_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared -Bsymbolic
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+8000 <addr_globl>:
+    8000:	00000000          	.word	0x00000000
+			8000: R_RISCV_RELATIVE	\*ABS\*\+0x8000
+
+0+8004 <addr_local>:
+	...
+			8004: R_RISCV_RELATIVE	\*ABS\*\+0x8004
+			8008: R_RISCV_RELATIVE	\*ABS\*\+0x100
+    800c:	00000200          	.word	0x00000200
+    8010:	00000000          	.word	0x00000000
+			8010: R_RISCV_32	undef
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d
new file mode 100644
index 00000000000..1d3686de353
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-abs32-pic.d
@@ -0,0 +1,13 @@ 
+#source: data-reloc.s
+#as: -march=rv64i -mabi=lp64 -defsym __abs__=1
+#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+8000 <.text>:
+    8000:	00000100          	.word	0x00000100
+    8004:	00000200          	.word	0x00000200
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d
new file mode 100644
index 00000000000..39b50e33044
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-addr32-pic.d
@@ -0,0 +1,4 @@ 
+#source: data-reloc.s
+#as: -march=rv64i -mabi=lp64 -defsym __addr__=1
+#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0  -shared
+#error: .*relocation R_RISCV_32 against non-absolute symbol `addr_globl' can not be used in RV64 when making a shared object.*
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d
new file mode 100644
index 00000000000..dab0ccc9260
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pic.d
@@ -0,0 +1,21 @@ 
+#source: data-reloc.s
+#as: -march=rv64i -mabi=lp64 -defsym __64_bit__=1 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
+#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+8000 <addr_globl>:
+	...
+			8000: R_RISCV_64	addr_globl
+
+0+8008 <addr_local>:
+	...
+			8008: R_RISCV_RELATIVE	\*ABS\*\+0x8008
+			8010: R_RISCV_64	abs
+    8018:	00000200          	.word	0x00000200
+	...
+			8020: R_RISCV_64	undef
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d
new file mode 100644
index 00000000000..fd6c470f680
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-pie.d
@@ -0,0 +1,21 @@ 
+#source: data-reloc.s
+#as: -march=rv64i -mabi=lp64 -defsym __64_bit__=1 -defsym __abs__=1 -defsym __addr__=1
+#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -pie
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+8000 <addr_globl>:
+	...
+			8000: R_RISCV_RELATIVE	\*ABS\*\+0x8000
+
+0+8008 <addr_local>:
+	...
+			8008: R_RISCV_RELATIVE	\*ABS\*\+0x8008
+    8010:	00000100          	.word	0x00000100
+    8014:	00000000          	.word	0x00000000
+    8018:	00000200          	.word	0x00000200
+    801c:	00000000          	.word	0x00000000
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d
new file mode 100644
index 00000000000..5d41f869b72
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-symbolic.d
@@ -0,0 +1,21 @@ 
+#source: data-reloc.s
+#as: -march=rv64i -mabi=lp64 -defsym __64_bit__=1 -defsym __abs__=1 -defsym __addr__=1 -defsym __undef__=1
+#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0 --defsym abs=0x100 --defsym abs_local=0x200 -shared -Bsymbolic
+#objdump: -dR
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+8000 <addr_globl>:
+	...
+			8000: R_RISCV_RELATIVE	\*ABS\*\+0x8000
+
+0+8008 <addr_local>:
+	...
+			8008: R_RISCV_RELATIVE	\*ABS\*\+0x8008
+			8010: R_RISCV_RELATIVE	\*ABS\*\+0x100
+    8018:	00000200          	.word	0x00000200
+	...
+			8020: R_RISCV_64	undef
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d
new file mode 100644
index 00000000000..e5de484142c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc-rv64-undef32-pic.d
@@ -0,0 +1,4 @@ 
+#source: data-reloc.s
+#as: -march=rv64i -mabi=lp64 -defsym __undef__=1
+#ld: -m[riscv_choose_lp64_emul] -Ttext 0x8000 --defsym _start=0x0  -shared
+#error: .*relocation R_RISCV_32 against non-absolute symbol `undef' can not be used in RV64 when making a shared object.*
diff --git a/ld/testsuite/ld-riscv-elf/data-reloc.s b/ld/testsuite/ld-riscv-elf/data-reloc.s
new file mode 100644
index 00000000000..37151500f77
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/data-reloc.s
@@ -0,0 +1,22 @@ 
+	.macro	DATA symbol
+.ifdef __64_bit__
+	.quad	\symbol
+.else
+	.word	\symbol
+.endif
+	.endm
+.ifdef __addr__
+	.globl  addr_globl
+addr_globl:
+	DATA	addr_globl
+addr_local:
+	DATA	addr_local
+.endif
+.ifdef __abs__
+	.hidden abs_local
+	DATA	abs
+	DATA	abs_local
+.endif
+.ifdef __undef__
+	DATA	undef
+.endif
diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s
index 23c7254ad5b..df0d33b97e2 100644
--- a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s
+++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s
@@ -20,4 +20,4 @@  main:
 
 	.data
 foo_addr:
-	.long	foo
+	.quad	foo
diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s
index 8aa64034706..cc1608a9803 100644
--- a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s
+++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s
@@ -23,4 +23,4 @@  main:
 
 	.data
 foo_addr:
-	.long	foo
+	.quad	foo
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 5dd6144efd3..1b2a5ce2cb2 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -217,6 +217,16 @@  if [istarget "riscv*-*-*"] {
     run_dump_test "shared-lib-nopic-03"
     run_dump_test "shared-lib-nopic-04"
 
+    run_dump_test "data-reloc-rv64-pic"
+    run_dump_test "data-reloc-rv64-pie"
+    run_dump_test "data-reloc-rv64-symbolic"
+    run_dump_test "data-reloc-rv32-pic"
+    run_dump_test "data-reloc-rv32-pie"
+    run_dump_test "data-reloc-rv32-symbolic"
+    run_dump_test "data-reloc-rv64-abs32-pic"
+    run_dump_test "data-reloc-rv64-addr32-pic"
+    run_dump_test "data-reloc-rv64-undef32-pic"
+
     # IFUNC testcases.
     # Check IFUNC by single type relocs.
     run_dump_test_ifunc "ifunc-reloc-call-01" rv32 exe
@@ -270,6 +280,11 @@  if [istarget "riscv*-*-*"] {
     run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pie
     run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pic
 
+    # TODO: Make the following tests work under RV32.
+    if [istarget "riscv32-*-*"] {
+      return
+    }
+
     # Setup shared libraries.
     run_ld_link_tests {
        { "Build shared library for IFUNC non-PLT caller"