[2/3] RISC-V: Clarify link behaviors of R_RISCV_32/64 relocations with ABS symbol.
Checks
Commit Message
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
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)
>
@@ -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;
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
new file mode 100644
@@ -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
@@ -20,4 +20,4 @@ main:
.data
foo_addr:
- .long foo
+ .quad foo
@@ -23,4 +23,4 @@ main:
.data
foo_addr:
- .long foo
+ .quad foo
@@ -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"