[PATCH 3/3] RISC-V: Added DT_RELR support
Nelson Chu
nelson@rivosinc.com
Sat Jun 7 08:36:41 GMT 2025
Porting by refering aarch64 and loongarch implementations.
1. RISC-V and loongarch both have relaxations, so there is also the same thing
that it's not safe to do relxations when updating the section layouts for relr.
2. RISC-V does not usually pre-fill values for R_RISCV_RELATIVE relocation, but
relr needs, so added *.d test cases to make sure the contents of relr are
pre-filled (relocated).
3. For relr readelf, added is_riscv_special_symbol_name to filter following
special symbols:
* mapping symbols
* __DATA_BEGIN__, __SDATA_BEGIN__ and __BSS_END__, which are only used for
counting gp in riscv.
---
bfd/elfnn-riscv.c | 512 +++++++++++++++++-
binutils/readelf.c | 17 +
binutils/testsuite/lib/binutils-common.exp | 3 +-
ld/emulparams/elf32lriscv.sh | 1 +
ld/emulparams/elf64lriscv.sh | 1 +
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 51 ++
.../ld-riscv-elf/relr-align-rv32-pic.d | 23 +
.../ld-riscv-elf/relr-align-rv32-pic.rd | 18 +
.../ld-riscv-elf/relr-align-rv64-pic.d | 41 ++
.../ld-riscv-elf/relr-align-rv64-pic.rd | 18 +
ld/testsuite/ld-riscv-elf/relr-align.s | 114 ++++
.../ld-riscv-elf/relr-data-rv32-pic.d | 22 +
.../ld-riscv-elf/relr-data-rv32-pic.rd | 14 +
.../ld-riscv-elf/relr-data-rv32-pie.d | 22 +
.../ld-riscv-elf/relr-data-rv32-pie.rd | 14 +
.../ld-riscv-elf/relr-data-rv64-pic.d | 22 +
.../ld-riscv-elf/relr-data-rv64-pic.rd | 14 +
.../ld-riscv-elf/relr-data-rv64-pie.d | 22 +
.../ld-riscv-elf/relr-data-rv64-pie.rd | 14 +
ld/testsuite/ld-riscv-elf/relr-data.s | 79 +++
ld/testsuite/ld-riscv-elf/relr-discard-pic.d | 14 +
ld/testsuite/ld-riscv-elf/relr-discard-pie.d | 11 +
ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.d | 21 +
.../ld-riscv-elf/relr-got-rv32-pic.rd | 11 +
ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.d | 21 +
.../ld-riscv-elf/relr-got-rv32-pie.rd | 11 +
ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.d | 23 +
.../ld-riscv-elf/relr-got-rv64-pic.rd | 11 +
ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.d | 23 +
.../ld-riscv-elf/relr-got-rv64-pie.rd | 11 +
ld/testsuite/ld-riscv-elf/relr-got.s | 31 ++
ld/testsuite/ld-riscv-elf/relr-relocs.ld | 23 +
ld/testsuite/ld-riscv-elf/relr-text-pic.d | 14 +
ld/testsuite/ld-riscv-elf/relr-text-pie.d | 14 +
ld/testsuite/ld-riscv-elf/relr-text.s | 10 +
35 files changed, 1251 insertions(+), 20 deletions(-)
create mode 100644 ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-align.s
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-data.s
create mode 100644 ld/testsuite/ld-riscv-elf/relr-discard-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-discard-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.rd
create mode 100644 ld/testsuite/ld-riscv-elf/relr-got.s
create mode 100644 ld/testsuite/ld-riscv-elf/relr-relocs.ld
create mode 100644 ld/testsuite/ld-riscv-elf/relr-text-pic.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-text-pie.d
create mode 100644 ld/testsuite/ld-riscv-elf/relr-text.s
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 2341447c421..4f29774f325 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -77,21 +77,27 @@
&& (H)->type == STT_GNU_IFUNC \
&& ((SEC)->flags & SEC_CODE) == 0))
-/* True if dynamic relocation should be generated. */
-#define RISCV_GENERATE_DYNAMIC_RELOC(PCREL, INFO, H, RESOLVED_TO_ZERO) \
- ((bfd_link_pic (INFO) \
- && ((H) == NULL \
- || (ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT && !(RESOLVED_TO_ZERO)) \
- || (H)->root.type != bfd_link_hash_undefweak) \
- && (!(PCREL) \
- || !SYMBOL_CALLS_LOCAL ((INFO), (H)))) \
- || (!bfd_link_pic (INFO) \
- && (H) != NULL \
- && (H)->dynindx != -1 \
- && !(H)->non_got_ref \
- && (((H)->def_dynamic && !(H)->def_regular) \
- || (H)->root.type == bfd_link_hash_undefweak \
- || (H)->root.type == bfd_link_hash_undefined)))
+/* True if dynamic relocation should be generated when generating a shared
+ library or PIE. */
+#define RISCV_GENERATE_DYNAMIC_RELOC_FOR_PIC(PCREL, INFO, H, RESOLVED_TO_ZERO) \
+ (bfd_link_pic (INFO) \
+ && ((H) == NULL \
+ || (ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT && !(RESOLVED_TO_ZERO)) \
+ || (H)->root.type != bfd_link_hash_undefweak) \
+ && (!(PCREL) \
+ || !SYMBOL_CALLS_LOCAL ((INFO), (H))))
+
+/* True if dynamic relocation should be generated when generating an
+ executable. We may need to keep relocations for symbols satisfied
+ by a dynamic library if we manage to avoid. */
+#define RISCV_GENERATE_DYNAMIC_RELOC_FOR_EXE(INFO, H) \
+ (!bfd_link_pic (INFO) \
+ && (H) != NULL \
+ && (H)->dynindx != -1 \
+ && !(H)->non_got_ref \
+ && (((H)->def_dynamic && !(H)->def_regular) \
+ || (H)->root.type == bfd_link_hash_undefweak \
+ || (H)->root.type == bfd_link_hash_undefined))
/* True if this input relocation should be copied to output. H->dynindx
may be -1 if this symbol was marked to become local. */
@@ -200,6 +206,39 @@ elfNN_riscv_mkobject (bfd *abfd)
sizeof (struct _bfd_riscv_elf_obj_tdata));
}
+struct relr_entry
+{
+ asection *sec;
+ bfd_vma off;
+};
+
+typedef struct _riscv_elf_section_data
+{
+ struct bfd_elf_section_data elf;
+
+ /* Handle interactions between DT_RELR and relaxation. */
+ struct relr_entry *relr;
+} _riscv_elf_section_data;
+
+#define riscv_elf_section_data(sec) \
+ ((_riscv_elf_section_data *) elf_section_data (sec))
+
+/* Allocate target specific section data. */
+
+static bool
+elfNN_riscv_new_section_hook (bfd *abfd, asection *sec)
+{
+ if (!sec->used_by_bfd)
+ {
+ struct _riscv_elf_section_data *sdata;
+ sdata = bfd_zalloc (abfd, sizeof (*sdata));
+ if (sdata == NULL)
+ return false;
+ sec->used_by_bfd = sdata;
+ }
+ return _bfd_elf_new_section_hook (abfd, sec);
+}
+
#include "elf/common.h"
#include "elf/internal.h"
@@ -232,6 +271,17 @@ struct riscv_elf_link_hash_table
/* Relocations for variant CC symbols may be present. */
int variant_cc;
+
+ /* Array of RELATIVE relocs to be emitted in DT_RELR format. */
+ bfd_size_type relr_alloc;
+ bfd_size_type relr_count;
+ struct relr_entry *relr;
+ /* Sorted output addresses of above RELATIVE relocs. */
+ bfd_vma *relr_sorted;
+ /* Layout recomputation count. */
+ bfd_size_type relr_layout_iter;
+ /* The section layouts are updating for relr. */
+ bool layout_mutating_for_relr;
};
/* Instruction access functions. */
@@ -1499,6 +1549,369 @@ allocate_local_ifunc_dynrelocs (void **slot, void *inf)
return allocate_ifunc_dynrelocs (h, inf);
}
+/* Record a relative relocation that will be emitted packed (DT_RELR).
+ Called after relocation sections are sized, so undo the size accounting
+ for this relocation. */
+
+static bool
+record_relr (struct riscv_elf_link_hash_table *htab, asection *sec,
+ bfd_vma off, asection *sreloc)
+{
+ struct relr_entry **sec_relr = &riscv_elf_section_data (sec)->relr;
+
+ /* Undo the relocation section size accounting. */
+ BFD_ASSERT (sreloc->size >= sizeof (ElfNN_External_Rela));
+ sreloc->size -= sizeof (ElfNN_External_Rela);
+
+ /* The packing format uses the last bit of the address so that
+ must be aligned. We don't pack relocations that may not be
+ aligned even though the final output address could end up
+ aligned, to avoid complex sizing logic for a rare case. */
+ BFD_ASSERT (off % 2 == 0 && sec->alignment_power > 0);
+ if (htab->relr_count >= htab->relr_alloc)
+ {
+ if (htab->relr_alloc == 0)
+ htab->relr_alloc = 4096;
+ else
+ htab->relr_alloc *= 2;
+ htab->relr = bfd_realloc (htab->relr,
+ htab->relr_alloc * sizeof (*htab->relr));
+ if (htab->relr == NULL)
+ return false;
+ }
+
+ htab->relr[htab->relr_count].sec = sec;
+ htab->relr[htab->relr_count].off = off;
+ if (*sec_relr == NULL)
+ *sec_relr = &htab->relr[htab->relr_count];
+ htab->relr_count++;
+ return true;
+}
+
+/* Follow allocate_dynrelocs, but only record relative relocations against the
+ GOT and undo their previous size accounting. */
+
+static bool
+record_relr_dyn_got_relocs (struct elf_link_hash_entry *h, void *inf)
+{
+ if (h->root.type == bfd_link_hash_indirect)
+ return true;
+ if (h->type == STT_GNU_IFUNC && h->def_regular)
+ return true;
+ if (h->got.refcount <= 0)
+ return true;
+ if (riscv_elf_hash_entry (h)->tls_type
+ & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLSDESC))
+ return true;
+
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+
+ /* Need to make sure gp is output as a dynamic symbol for pde? */
+
+ if (bfd_link_pic (info) && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+ {
+ /* Check got relocs in riscv_elf_relocate_section. */
+ bool relative_reloc = SYMBOL_REFERENCES_LOCAL (info, h)
+ && !bfd_is_abs_symbol (&h->root);
+ if (relative_reloc)
+ if (!record_relr (htab, htab->elf.sgot, h->got.offset,
+ htab->elf.srelgot))
+ return false;
+ }
+ return true;
+}
+
+/* Record packed relative relocs against the GOT for local symbols.
+ Undo the size accounting of riscv_elf_late_size_sections. */
+
+static bool
+record_relr_local_got_relocs (bfd *input_bfd, struct bfd_link_info *info)
+{
+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (input_bfd);
+ bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
+ char *local_tls_type = _bfd_riscv_elf_local_got_tls_type (input_bfd);
+
+ if (!bfd_link_pic (info)
+ || !local_got_refcounts
+ || !local_got_offsets
+ || !local_tls_type)
+ return true;
+
+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+ for (unsigned int i = 0; i < symtab_hdr->sh_info; i++)
+ {
+ if (local_got_refcounts[i] <= 0)
+ continue;
+ if ((local_tls_type[i] & GOT_NORMAL) == 0)
+ continue;
+
+ bfd_vma off = local_got_offsets[i];
+
+ /* FIXME: If the local symbol is in SHN_ABS then emitting
+ a relative relocation is not correct, but it seems to
+ be wrong in riscv_elf_relocate_section too. */
+ if (!record_relr (htab, htab->elf.sgot, off, htab->elf.srelgot))
+ return false;
+ }
+ return true;
+}
+
+/* Follows the logic of riscv_elf_relocate_section to decide which
+ relocations will become relative and possible to pack. Ignore
+ relocations against the GOT, those are handled separately per-symbol.
+ Undo the size accounting of the packed relocations and record them
+ so the relr section can be sized later. */
+
+static bool
+record_relr_non_got_relocs (bfd *input_bfd, struct bfd_link_info *info,
+ asection *sec)
+{
+ if (sec->reloc_count == 0)
+ return true;
+ if ((sec->flags & (SEC_RELOC | SEC_ALLOC | SEC_DEBUGGING))
+ != (SEC_RELOC | SEC_ALLOC))
+ return true;
+ if (sec->alignment_power == 0)
+ return true;
+ if (discarded_section (sec))
+ return true;
+ asection *sreloc = elf_section_data (sec)->sreloc;
+ if (sreloc == NULL)
+ return true;
+
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
+ const Elf_Internal_Rela * relocs =
+ _bfd_elf_link_info_read_relocs (input_bfd, info, sec, NULL, NULL,
+ info->keep_memory);
+ BFD_ASSERT (relocs != NULL);
+
+ const Elf_Internal_Rela *rel = relocs;
+ const Elf_Internal_Rela *rel_end = relocs + sec->reloc_count;
+ for (; rel < rel_end; rel++)
+ {
+ unsigned int r_symndx = ELFNN_R_SYM (rel->r_info);
+ unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
+
+ /* Handle relocs that can become R_RISCV_RELATIVE,
+ but not ones against the GOT as those are handled
+ separately per-symbol. */
+ if (r_type != R_RISCV_32 && r_type != R_RISCV_64)
+ continue;
+ /* Can only pack relocation against an aligned address. */
+ if (rel->r_offset % 2 != 0)
+ continue;
+
+ struct elf_link_hash_entry *h = NULL;
+ asection *def_sec = NULL;
+ bool resolved_to_zero = false;
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ /* A local symbol. */
+ Elf_Internal_Sym *isym;
+ isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
+ input_bfd, r_symndx);
+ BFD_ASSERT (isym != NULL);
+
+ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+ continue;
+
+ def_sec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
+ }
+ else
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_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;
+
+ /* Filter out symbols that cannot have a relative reloc. */
+ if (h->dyn_relocs == NULL)
+ continue;
+ if (bfd_is_abs_symbol (&h->root))
+ continue;
+ if (h->type == STT_GNU_IFUNC)
+ continue;
+
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ def_sec = h->root.u.def.section;
+
+ resolved_to_zero = UNDEFWEAK_NO_DYNAMIC_RELOC (info, h);
+ }
+
+ if (def_sec != NULL && discarded_section (def_sec))
+ continue;
+
+ /* Same logic as in riscv_elf_relocate_section, for R_RISCV_32/64.
+ Except conditionals trimmed that cannot result a reltive reloc. */
+ reloc_howto_type *howto = riscv_elf_rtype_to_howto (input_bfd, r_type);
+ if (RISCV_GENERATE_DYNAMIC_RELOC_FOR_PIC (howto->pc_relative, info, h,
+ resolved_to_zero))
+ {
+ if (RISCV_COPY_INPUT_RELOC (info, h))
+ continue;
+
+ if (!record_relr (htab, sec, rel->r_offset, sreloc))
+ return false;
+ }
+ }
+ return true;
+}
+
+static int
+cmp_relr_addr (const void *p, const void *q)
+{
+ const bfd_vma *a = p;
+ const bfd_vma *b = q;
+ return *a < *b ? -1 : *a > *b ? 1 : 0;
+}
+
+/* Produce a malloc'd sorted array of reloc addresses in htab->relr_sorted.
+ Returns false on allocation failure. */
+
+static bool
+sort_relr (struct bfd_link_info *info,
+ struct riscv_elf_link_hash_table *htab)
+{
+ if (htab->relr_count == 0)
+ return true;
+
+ bfd_vma *addr = htab->relr_sorted;
+ if (addr == NULL)
+ {
+ addr = bfd_malloc (htab->relr_count * sizeof (*addr));
+ if (addr == NULL)
+ return false;
+ htab->relr_sorted = addr;
+ }
+
+ for (bfd_size_type i = 0; i < htab->relr_count; i++)
+ {
+ bfd_vma off = _bfd_elf_section_offset (info->output_bfd, info,
+ htab->relr[i].sec,
+ htab->relr[i].off);
+ addr[i] = htab->relr[i].sec->output_section->vma
+ + htab->relr[i].sec->output_offset
+ + off;
+ }
+ qsort (addr, htab->relr_count, sizeof (*addr), cmp_relr_addr);
+ return true;
+}
+
+/* Size of a relr entry and a relocated location. */
+#define RELR_SZ (ARCH_SIZE / 8)
+/* Number of consecutive locations a relr bitmap entry references. */
+#define RELR_N (ARCH_SIZE - 1)
+
+/* Size .relr.dyn whenever the layout changes, the number of packed
+ relocs are unchanged but the packed representation can. */
+
+static bool
+riscv_elf_size_relative_relocs (struct bfd_link_info *info,
+ bool *need_layout)
+{
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+ asection *srelrdyn = htab->elf.srelrdyn;
+ *need_layout = false;
+
+ if (!sort_relr (info, htab))
+ return false;
+ bfd_vma *addr = htab->relr_sorted;
+
+ BFD_ASSERT (srelrdyn != NULL);
+ bfd_size_type oldsize = srelrdyn->size;
+ srelrdyn->size = 0;
+ for (bfd_size_type i = 0; i < htab->relr_count; )
+ {
+ bfd_vma base = addr[i];
+ i++;
+ srelrdyn->size += RELR_SZ;
+ base += RELR_SZ;
+ for (;;)
+ {
+ bfd_size_type start_i = i;
+ while (i < htab->relr_count
+ && addr[i] - base < RELR_N * RELR_SZ
+ && (addr[i] - base) % RELR_SZ == 0)
+ i++;
+ if (i == start_i)
+ break;
+ srelrdyn->size += RELR_SZ;
+ base += RELR_N * RELR_SZ;
+ }
+ }
+ if (srelrdyn->size != oldsize)
+ {
+ *need_layout = true;
+ /* Stop after a few iterations in case the layout does not converge,
+ we can do this when the size would shrink. */
+ if (htab->relr_layout_iter++ > 5 && srelrdyn->size < oldsize)
+ {
+ srelrdyn->size = oldsize;
+ *need_layout = false;
+ }
+ }
+ htab->layout_mutating_for_relr = *need_layout;
+ return true;
+}
+
+/* Emit the .relr.dyn section after it is sized and the layout is fixed. */
+
+static bool
+riscv_elf_finish_relative_relocs (struct bfd_link_info *info)
+{
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+ asection *srelrdyn = htab->elf.srelrdyn;
+ bfd *dynobj = htab->elf.dynobj;
+
+ if (srelrdyn == NULL || srelrdyn->size == 0)
+ return true;
+ srelrdyn->contents = bfd_alloc (dynobj, srelrdyn->size);
+ if (srelrdyn->contents == NULL)
+ return false;
+ srelrdyn->alloced = 1;
+ bfd_vma *addr = htab->relr_sorted;
+ bfd_byte *loc = srelrdyn->contents;
+ for (bfd_size_type i = 0; i < htab->relr_count; )
+ {
+ bfd_vma base = addr[i];
+ i++;
+ bfd_put_NN (dynobj, base, loc);
+ loc += RELR_SZ;
+ base += RELR_SZ;
+ for (;;)
+ {
+ bfd_vma bits = 0;
+ while (i < htab->relr_count)
+ {
+ bfd_vma delta = addr[i] - base;
+ if (delta >= RELR_N * RELR_SZ || delta % RELR_SZ != 0)
+ break;
+ bits |= (bfd_vma) 1 << (delta / RELR_SZ);
+ i++;
+ }
+ if (bits == 0)
+ break;
+ bfd_put_NN (dynobj, (bits << 1) | 1, loc);
+ loc += RELR_SZ;
+ base += RELR_N * RELR_SZ;
+ }
+ }
+ free (addr);
+ htab->relr_sorted = NULL;
+ /* Pad any excess with 1's, a do-nothing encoding. */
+ while (loc < srelrdyn->contents + srelrdyn->size)
+ {
+ bfd_put_NN (dynobj, 1, loc);
+ loc += RELR_SZ;
+ }
+ return true;
+}
+
static bool
riscv_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
{
@@ -1648,6 +2061,27 @@ riscv_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
htab->elf.sgotplt->size = 0;
}
+ /* Record the relative relocations that will be packed and undo the
+ size allocation for them in .rela.*. The size of .relr.dyn will be
+ computed later iteratively since it depends on the final layout. */
+ if (info->enable_dt_relr && !bfd_link_relocatable (info))
+ {
+ elf_link_hash_traverse (&htab->elf, record_relr_dyn_got_relocs, info);
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
+ {
+ if (!is_riscv_elf (ibfd))
+ continue;
+
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ if (!record_relr_non_got_relocs (ibfd, info, s))
+ return false;
+
+ if (!record_relr_local_got_relocs (ibfd, info))
+ return false;
+ }
+ }
+
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
@@ -1677,6 +2111,15 @@ riscv_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
s->reloc_count = 0;
}
}
+ else if (s == htab->elf.srelrdyn)
+ {
+ /* Remove .relr.dyn based on relr_count, not size, since
+ it is not sized yet. */
+ if (htab->relr_count == 0)
+ s->flags |= SEC_EXCLUDE;
+ /* Allocate contents later. */
+ continue;
+ }
else
{
/* It's not one of our sections. */
@@ -2701,7 +3144,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
off &= ~1;
else
{
- if (bfd_link_pic (info))
+ if (bfd_link_pic (info) && !info->enable_dt_relr)
{
asection *s;
Elf_Internal_Rela outrel;
@@ -2950,8 +3393,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
if ((input_section->flags & SEC_ALLOC) == 0)
break;
- if (RISCV_GENERATE_DYNAMIC_RELOC (howto->pc_relative, info, h,
- resolved_to_zero))
+ if (RISCV_GENERATE_DYNAMIC_RELOC_FOR_PIC (howto->pc_relative, info,
+ h, resolved_to_zero)
+ || RISCV_GENERATE_DYNAMIC_RELOC_FOR_EXE (info, h))
{
Elf_Internal_Rela outrel;
asection *sreloc;
@@ -2991,6 +3435,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
outrel.r_addend = rel->r_addend;
}
+ else if (info->enable_dt_relr
+ && input_section->alignment_power != 0
+ && rel->r_offset % 2 == 0)
+ {
+ /* Don't emit a relative relocation that is packed, only
+ apply the addend. */
+ goto do_relocation;
+ }
else
{
/* This symbol is local, or marked to become local. */
@@ -3462,6 +3914,10 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
BFD_ASSERT ((h->got.offset & 1) != 0); */
+ /* Don't emit relative relocs if they are packed. */
+ if (info->enable_dt_relr)
+ goto skip_got_reloc;
+
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
@@ -3498,6 +3954,8 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
}
}
+ skip_got_reloc:
+
if (h->needs_copy)
{
Elf_Internal_Rela rela;
@@ -4578,6 +5036,16 @@ _riscv_relax_delete_bytes (bfd *abfd,
}
}
+ /* Adjust the offsets for all record relr in this section. */
+ struct relr_entry *relr = riscv_elf_section_data (sec)->relr;
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (link_info);
+ struct relr_entry *relr_end = NULL;
+ if (htab->relr_count)
+ relr_end = htab->relr + htab->relr_count;
+ for (; relr && relr < relr_end && relr->sec == sec; relr++)
+ if (relr->off > addr && relr->off < toaddr)
+ relr->off -= count;
+
return true;
}
@@ -5214,7 +5682,10 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
&& info->relax_pass == 0)
/* The exp_seg_relro_adjust is enum phase_enum (0x4),
and defined in ld/ldexp.h. */
- || *(htab->data_segment_phase) == 4)
+ || *(htab->data_segment_phase) == 4
+ /* It's not safe to do relaxations when relr are updating the section
+ layouts. */
+ || htab->layout_mutating_for_relr)
return true;
/* Record the first relax section, so that we can reset the
@@ -5798,10 +6269,13 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
#define elf_info_to_howto riscv_info_to_howto_rela
#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section
#define bfd_elfNN_mkobject elfNN_riscv_mkobject
+#define bfd_elfNN_new_section_hook elfNN_riscv_new_section_hook
#define elf_backend_additional_program_headers \
riscv_elf_additional_program_headers
#define elf_backend_modify_segment_map riscv_elf_modify_segment_map
#define elf_backend_merge_symbol_attribute riscv_elf_merge_symbol_attribute
+#define elf_backend_size_relative_relocs riscv_elf_size_relative_relocs
+#define elf_backend_finish_relative_relocs riscv_elf_finish_relative_relocs
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
diff --git a/binutils/readelf.c b/binutils/readelf.c
index dd1871d8c75..ab904664231 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -1663,6 +1663,20 @@ is_aarch64_special_symbol_name (const char *name)
return name[2] == 0 || name[2] == '.';
}
+/* See riscv_elf_is_mapping_symbols. */
+
+static bool
+is_riscv_special_symbol_name (const char *name)
+{
+ return (!strcmp (name, "$d")
+ || !strcmp (name, "$x")
+ || !strncmp (name, "$xrv", 4)
+ /* Only used for counting gp in risc-v. */
+ || !strcmp (name, "__DATA_BEGIN__")
+ || !strcmp (name, "__SDATA_BEGIN__")
+ || !strcmp (name, "__BSS_END__"));
+}
+
static bool
is_special_symbol_name (Filedata * filedata, const char * s)
{
@@ -1671,6 +1685,9 @@ is_special_symbol_name (Filedata * filedata, const char * s)
case EM_AARCH64:
return is_aarch64_special_symbol_name (s);
+ case EM_RISCV:
+ return is_riscv_special_symbol_name (s);
+
default:
return false;
}
diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
index 41d94d256ec..4cc75f6edaf 100644
--- a/binutils/testsuite/lib/binutils-common.exp
+++ b/binutils/testsuite/lib/binutils-common.exp
@@ -472,7 +472,8 @@ proc supports_dt_relr {} {
|| [istarget i?86-*-*]
|| [istarget powerpc64*-*-*]
|| [istarget aarch64*-*-*]
- || [istarget loongarch64*-*-*])
+ || [istarget loongarch64*-*-*]
+ || [istarget riscv*-*-*])
&& ([istarget *-*-linux*]
|| [istarget *-*-gnu*]) } {
return 1
diff --git a/ld/emulparams/elf32lriscv.sh b/ld/emulparams/elf32lriscv.sh
index da0d7cf54f4..c85cf179b6d 100644
--- a/ld/emulparams/elf32lriscv.sh
+++ b/ld/emulparams/elf32lriscv.sh
@@ -1,6 +1,7 @@
# RV32 code using ILP32D ABI.
# ABI not in emulation name to avoid breaking backward compatibility.
source_sh ${srcdir}/emulparams/elf32lriscv-defs.sh
+source_sh ${srcdir}/emulparams/dt-relr.sh
OUTPUT_FORMAT="elf32-littleriscv"
# On Linux, first look for 32 bit ILP32D target libraries in /lib/ilp32d as per
diff --git a/ld/emulparams/elf64lriscv.sh b/ld/emulparams/elf64lriscv.sh
index e07a0648735..1ea5b7fc637 100644
--- a/ld/emulparams/elf64lriscv.sh
+++ b/ld/emulparams/elf64lriscv.sh
@@ -1,6 +1,7 @@
# RV64 code using LP64D ABI.
# ABI not in emulation name to avoid breaking backward compatibility.
source_sh ${srcdir}/emulparams/elf64lriscv-defs.sh
+source_sh ${srcdir}/emulparams/dt-relr.sh
OUTPUT_FORMAT="elf64-littleriscv"
# On Linux, first look for 64 bit LP64D target libraries in /lib64/lp64d as per
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index d68a9145dcd..2b31d54ac1e 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -78,6 +78,41 @@ proc run_dump_test_ifunc { name target output} {
"$name-$target.$ext"]]
}
+
+proc run_dump_test_relr { name target output} {
+ # TODO: big-endian for *.d test cases?
+ set asflags "-mlittle-endian"
+ set ldflags "-z pack-relative-relocs -T relr-relocs.ld"
+ switch -- $output {
+ pie {
+ set ext "pie"
+ set ldflags "$ldflags -pie"
+ }
+ pic {
+ set ext "so"
+ set ldflags "$ldflags -shared"
+ }
+ }
+ switch -- $target {
+ rv32 {
+ set asflags "$asflags -march=rv32i -mabi=ilp32"
+ set ldflags "$ldflags -m[riscv_choose_ilp32_emul]"
+ }
+ rv64 {
+ set asflags "$asflags -march=rv64i -mabi=lp64 -defsym __64_bit__=1"
+ set ldflags "$ldflags -m[riscv_choose_lp64_emul]"
+ }
+ }
+ run_ld_link_tests [list \
+ [list "$name ($target-$output)" \
+ "$ldflags" "" \
+ "$asflags" \
+ [list "$name.s"] \
+ [concat [list "readelf -rW $name-$target-$output.rd"] \
+ [list "objdump -dsw $name-$target-$output.d"]] \
+ "$name-$target.$ext"]]
+}
+
proc run_relax_twice_test {} {
global as
global ld
@@ -230,6 +265,22 @@ if [istarget "riscv*-*-*"] {
run_dump_test "discard-pie"
run_dump_test "discard-pic"
+ # RELR
+ run_dump_test_relr "relr-data" rv32 pie
+ run_dump_test_relr "relr-data" rv32 pic
+ run_dump_test_relr "relr-got" rv32 pie
+ run_dump_test_relr "relr-got" rv32 pic
+ run_dump_test_relr "relr-align" rv32 pic
+ run_dump_test_relr "relr-data" rv64 pie
+ run_dump_test_relr "relr-data" rv64 pic
+ run_dump_test_relr "relr-got" rv64 pie
+ run_dump_test_relr "relr-got" rv64 pic
+ run_dump_test_relr "relr-align" rv64 pic
+ run_dump_test "relr-text-pie"
+ run_dump_test "relr-text-pic"
+ run_dump_test "relr-discard-pie"
+ run_dump_test "relr-discard-pic"
+
# IFUNC testcases.
# Check IFUNC by single type relocs.
run_dump_test_ifunc "ifunc-reloc-call-01" rv32 exe
diff --git a/ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.d b/ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.d
new file mode 100644
index 00000000000..31eea11c42f
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.d
@@ -0,0 +1,23 @@
+#...
+Contents of section .data:
+ 12340000 00000100 00000100 00000000 00000000.*
+ 12340010 00000000 01000000 01000000 00000000.*
+ 12340020 00000100 00000000 00000000 01000000.*
+ 12340030 00000000 00000100 01000000 02000000.*
+ 12340040 03000000 04000000 05000000 06000000.*
+ 12340050 07000000 08000000 09000000 0a000000.*
+ 12340060 0b000000 0c000000 0d000000 0e000000.*
+ 12340070 0f000000 10000000 11000000 12000000.*
+ 12340080 13000000 14000000 15000000 16000000.*
+ 12340090 17000000 18000000 19000000 1a000000.*
+ 123400a0 1b000000 1c000000 1d000000 1e000000.*
+ 123400b0 1f000000 20000100 21000000 22000000.*
+ 123400c0 23000000 24000000 25000000 26000000.*
+ 123400d0 27000000 28000000 29000000 2a000000.*
+ 123400e0 2b000000 2c000000 2d000000 2e000000.*
+ 123400f0 2f000000 30000000 31000000 32000000.*
+ 12340100 33000000 34000000 35000000 36000000.*
+ 12340110 37000000 38000000 39000000 3a000000.*
+ 12340120 3b000000 3c000000 3d000000 3e000000.*
+ 12340130 3f000100 40000100.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.rd b/ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.rd
new file mode 100644
index 00000000000..01a08671d3c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-align-rv32-pic.rd
@@ -0,0 +1,18 @@
+Relocation section '\.rela\.dyn'.*contains 3 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+12340009[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10000
+1234000d[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10000
+12340025[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10000
+
+Relocation section '\.relr\.dyn'.*contains 10 entries which relocate 10 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+12340000[ ]+12340000[ ]+double_0
+0001:[ ]+00000003[ ]+12340004[ ]+double_0 \+ 0x4
+0002:[ ]+12340012[ ]+12340012[ ]+double_2
+0003:[ ]+00000003[ ]+12340016[ ]+double_2 \+ 0x4
+0004:[ ]+12340020[ ]+12340020[ ]+single_0
+0005:[ ]+1234002a[ ]+1234002a[ ]+single_2
+0006:[ ]+12340034[ ]+12340034[ ]+big
+0007:[ ]+123400b4[ ]+123400b4[ ]+big \+ 0x80
+0008:[ ]+80000001[ ]+12340130[ ]+big \+ 0xfc
+0009:[ ]+00000003[ ]+12340134[ ]+big \+ 0x100
diff --git a/ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.d b/ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.d
new file mode 100644
index 00000000000..38d81f8da5c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.d
@@ -0,0 +1,41 @@
+#...
+Contents of section .data:
+ 12340000 00000100 00000000 00000100 00000000.*
+ 12340010 00000000 00000000 00000000 00000000.*
+ 12340020 00000000 01000000 00000000 01000000.*
+ 12340030 00000000 00000000 00000100 00000000.*
+ 12340040 00000000 00000000 00000000 01000000.*
+ 12340050 00000000 00000000 00000100 00000000.*
+ 12340060 01000000 00000000 02000000 00000000.*
+ 12340070 03000000 00000000 04000000 00000000.*
+ 12340080 05000000 00000000 06000000 00000000.*
+ 12340090 07000000 00000000 08000000 00000000.*
+ 123400a0 09000000 00000000 0a000000 00000000.*
+ 123400b0 0b000000 00000000 0c000000 00000000.*
+ 123400c0 0d000000 00000000 0e000000 00000000.*
+ 123400d0 0f000000 00000000 10000000 00000000.*
+ 123400e0 11000000 00000000 12000000 00000000.*
+ 123400f0 13000000 00000000 14000000 00000000.*
+ 12340100 15000000 00000000 16000000 00000000.*
+ 12340110 17000000 00000000 18000000 00000000.*
+ 12340120 19000000 00000000 1a000000 00000000.*
+ 12340130 1b000000 00000000 1c000000 00000000.*
+ 12340140 1d000000 00000000 1e000000 00000000.*
+ 12340150 1f000000 00000000 20000100 00000000.*
+ 12340160 21000000 00000000 22000000 00000000.*
+ 12340170 23000000 00000000 24000000 00000000.*
+ 12340180 25000000 00000000 26000000 00000000.*
+ 12340190 27000000 00000000 28000000 00000000.*
+ 123401a0 29000000 00000000 2a000000 00000000.*
+ 123401b0 2b000000 00000000 2c000000 00000000.*
+ 123401c0 2d000000 00000000 2e000000 00000000.*
+ 123401d0 2f000000 00000000 30000000 00000000.*
+ 123401e0 31000000 00000000 32000000 00000000.*
+ 123401f0 33000000 00000000 34000000 00000000.*
+ 12340200 35000000 00000000 36000000 00000000.*
+ 12340210 37000000 00000000 38000000 00000000.*
+ 12340220 39000000 00000000 3a000000 00000000.*
+ 12340230 3b000000 00000000 3c000000 00000000.*
+ 12340240 3d000000 00000000 3e000000 00000000.*
+ 12340250 3f000100 00000000 40000100 00000000.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.rd b/ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.rd
new file mode 100644
index 00000000000..97a4d8c290e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-align-rv64-pic.rd
@@ -0,0 +1,18 @@
+Relocation section '\.rela\.dyn'.*contains 3 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+0000000012340011[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10000
+0000000012340019[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10000
+0000000012340041[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10000
+
+Relocation section '\.relr\.dyn'.*contains 9 entries which relocate 10 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000012340000[ ]+0000000012340000[ ]+double_0
+0001:[ ]+0000000000000003[ ]+0000000012340008[ ]+double_0 \+ 0x8
+0002:[ ]+0000000012340022[ ]+0000000012340022[ ]+double_2
+0003:[ ]+0000000000000003[ ]+000000001234002a[ ]+double_2 \+ 0x8
+0004:[ ]+0000000012340038[ ]+0000000012340038[ ]+single_0
+0005:[ ]+000000001234004a[ ]+000000001234004a[ ]+single_2
+0006:[ ]+0000000012340058[ ]+0000000012340058[ ]+big
+0007:[ ]+8000000100000001[ ]+0000000012340158[ ]+big \+ 0x100
+[ ]+0000000012340250[ ]+big \+ 0x1f8
+0008:[ ]+0000000000000003[ ]+0000000012340258[ ]+big \+ 0x200
diff --git a/ld/testsuite/ld-riscv-elf/relr-align.s b/ld/testsuite/ld-riscv-elf/relr-align.s
new file mode 100644
index 00000000000..9b19f88f5ec
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-align.s
@@ -0,0 +1,114 @@
+# Test DT_RELR with differently aligned relative relocs.
+
+.macro data value
+.ifdef __64_bit__
+ .quad \value
+.else
+ .long \value
+.endif
+.endm
+
+.text
+.global _start
+_start:
+foo:
+
+.data
+.p2align 3
+double_0:
+data foo
+data foo
+.byte 0
+double_1:
+data foo
+data foo
+.byte 0
+double_2:
+data foo
+data foo
+.byte 0
+.byte 0
+.byte 0
+.byte 0
+.byte 0
+.byte 0
+single_0:
+data foo
+.byte 0
+single_1:
+data foo
+.byte 0
+single_2:
+data foo
+.byte 0
+.byte 0
+.byte 0
+.byte 0
+.byte 0
+.byte 0
+big:
+data foo
+data 1
+data 2
+data 3
+data 4
+data 5
+data 6
+data 7
+data 8
+data 9
+data 10
+data 11
+data 12
+data 13
+data 14
+data 15
+data 16
+data 17
+data 18
+data 19
+data 20
+data 21
+data 22
+data 23
+data 24
+data 25
+data 26
+data 27
+data 28
+data 29
+data 30
+data 31
+data foo + 32
+data 33
+data 34
+data 35
+data 36
+data 37
+data 38
+data 39
+data 40
+data 41
+data 42
+data 43
+data 44
+data 45
+data 46
+data 47
+data 48
+data 49
+data 50
+data 51
+data 52
+data 53
+data 54
+data 55
+data 56
+data 57
+data 58
+data 59
+data 60
+data 61
+data 62
+data foo + 63
+data foo + 64
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.d b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.d
new file mode 100644
index 00000000000..4af2318123a
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.d
@@ -0,0 +1,22 @@
+#...
+Contents of section .data.unaligned_local:
+ 12340000 00000000.*
+Contents of section .data.unaligned_hidden:
+ 12340004 00000000.*
+Contents of section .data.unaligned_global:
+ 12340008 00000000.*
+Contents of section .data.unaligned_DYNAMIC:
+ 1234000c 00000000.*
+Contents of section .data.aligned_local:
+ 12340010 04000100.*
+Contents of section .data.aligned_hidden:
+ 12340014 08000100.*
+Contents of section .data.aligned_global:
+ 12340018 00000000.*
+Contents of section .data.aligned_global_abs:
+ 1234001c 2a000000.*
+Contents of section .data.aligned_weak_undef:
+ 12340020 00000000.*
+Contents of section .data.aligned_DYNAMIC:
+ 12340024 28003412.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.rd b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.rd
new file mode 100644
index 00000000000..45da4525ba8
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pic.rd
@@ -0,0 +1,14 @@
+Relocation section '\.rela\.dyn'.*contains 6 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+12340000[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10004
+12340004[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10008
+1234000c[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+12340028
+12340008[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+0001000c[ ]+sym_global \+ 0
+12340018[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+0001000c[ ]+sym_global \+ 0
+12340020[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+00000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 3 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+12340010[ ]+12340010[ ]+aligned_local
+0001:[ ]+00000023[ ]+12340014[ ]+aligned_hidden
+[ ]+12340024[ ]+aligned_DYNAMIC
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.d b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.d
new file mode 100644
index 00000000000..71e081ccdca
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.d
@@ -0,0 +1,22 @@
+#...
+Contents of section .data.unaligned_local:
+ 12340000 00000000.*
+Contents of section .data.unaligned_hidden:
+ 12340004 00000000.*
+Contents of section .data.unaligned_global:
+ 12340008 00000000.*
+Contents of section .data.unaligned_DYNAMIC:
+ 1234000c 00000000.*
+Contents of section .data.aligned_local:
+ 12340010 04000100.*
+Contents of section .data.aligned_hidden:
+ 12340014 08000100.*
+Contents of section .data.aligned_global:
+ 12340018 0c000100.*
+Contents of section .data.aligned_global_abs:
+ 1234001c 2a000000.*
+Contents of section .data.aligned_weak_undef:
+ 12340020 00000000.*
+Contents of section .data.aligned_DYNAMIC:
+ 12340024 28003412.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.rd b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.rd
new file mode 100644
index 00000000000..99e733f93c2
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv32-pie.rd
@@ -0,0 +1,14 @@
+Relocation section '\.rela\.dyn'.*contains 5 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+12340000[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10004
+12340004[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10008
+12340008[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+1000c
+1234000c[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+12340028
+12340020[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+00000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 4 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+12340010[ ]+12340010[ ]+aligned_local
+0001:[ ]+00000027[ ]+12340014[ ]+aligned_hidden
+[ ]+12340018[ ]+aligned_global
+[ ]+12340024[ ]+aligned_DYNAMIC
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.d b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.d
new file mode 100644
index 00000000000..0e3e1627dc5
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.d
@@ -0,0 +1,22 @@
+#...
+Contents of section .data.unaligned_local:
+ 12340000 00000000 00000000.*
+Contents of section .data.unaligned_hidden:
+ 12340008 00000000 00000000.*
+Contents of section .data.unaligned_global:
+ 12340010 00000000 00000000.*
+Contents of section .data.unaligned_DYNAMIC:
+ 12340018 00000000 00000000.*
+Contents of section .data.aligned_local:
+ 12340020 04000100 00000000.*
+Contents of section .data.aligned_hidden:
+ 12340028 08000100 00000000.*
+Contents of section .data.aligned_global:
+ 12340030 00000000 00000000.*
+Contents of section .data.aligned_global_abs:
+ 12340038 2a000000 00000000.*
+Contents of section .data.aligned_weak_undef:
+ 12340040 00000000 00000000.*
+Contents of section .data.aligned_DYNAMIC:
+ 12340048 50003412 00000000.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.rd b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.rd
new file mode 100644
index 00000000000..8bbd2e45a5e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pic.rd
@@ -0,0 +1,14 @@
+Relocation section '\.rela\.dyn'.*contains 6 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+0000000012340000[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10004
+0000000012340008[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10008
+0000000012340018[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+12340050
+0000000012340010[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000001000c[ ]+sym_global \+ 0
+0000000012340030[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000001000c[ ]+sym_global \+ 0
+0000000012340040[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+0000000000000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 3 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000012340020[ ]+0000000012340020[ ]+aligned_local
+0001:[ ]+0000000000000023[ ]+0000000012340028[ ]+aligned_hidden
+[ ]+0000000012340048[ ]+aligned_DYNAMIC
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.d b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.d
new file mode 100644
index 00000000000..0f940b325a8
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.d
@@ -0,0 +1,22 @@
+#...
+Contents of section .data.unaligned_local:
+ 12340000 00000000 00000000.*
+Contents of section .data.unaligned_hidden:
+ 12340008 00000000 00000000.*
+Contents of section .data.unaligned_global:
+ 12340010 00000000 00000000.*
+Contents of section .data.unaligned_DYNAMIC:
+ 12340018 00000000 00000000.*
+Contents of section .data.aligned_local:
+ 12340020 04000100 00000000.*
+Contents of section .data.aligned_hidden:
+ 12340028 08000100 00000000.*
+Contents of section .data.aligned_global:
+ 12340030 0c000100 00000000.*
+Contents of section .data.aligned_global_abs:
+ 12340038 2a000000 00000000.*
+Contents of section .data.aligned_weak_undef:
+ 12340040 00000000 00000000.*
+Contents of section .data.aligned_DYNAMIC:
+ 12340048 50003412 00000000.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.rd b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.rd
new file mode 100644
index 00000000000..6a7b8875133
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data-rv64-pie.rd
@@ -0,0 +1,14 @@
+Relocation section '\.rela\.dyn'.*contains 5 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+0000000012340000[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10004
+0000000012340008[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+10008
+0000000012340010[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+1000c
+0000000012340018[ ]+[0-9a-f]+[ ]+R_RISCV_RELATIVE[ ]+12340050
+0000000012340040[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+0000000000000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 4 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000012340020[ ]+0000000012340020[ ]+aligned_local
+0001:[ ]+0000000000000027[ ]+0000000012340028[ ]+aligned_hidden
+[ ]+0000000012340030[ ]+aligned_global
+[ ]+0000000012340048[ ]+aligned_DYNAMIC
diff --git a/ld/testsuite/ld-riscv-elf/relr-data.s b/ld/testsuite/ld-riscv-elf/relr-data.s
new file mode 100644
index 00000000000..1198a730226
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-data.s
@@ -0,0 +1,79 @@
+# Test symbol references in .data when used with DT_RELR.
+# Relocations for unaligned sections are currently not packed.
+
+.macro data value
+.ifdef __64_bit__
+ .quad \value
+.else
+ .long \value
+.endif
+.endm
+
+.text
+.global _start
+_start:
+ nop
+
+sym_local:
+ nop
+
+.global sym_hidden
+.hidden sym_hidden
+sym_hidden:
+ nop
+
+.global sym_global
+sym_global:
+ nop
+
+.global sym_global_abs
+.set sym_global_abs, 42
+
+.global sym_weak_undef
+.weak sym_weak_undef
+
+.section .data.unaligned_local
+unaligned_local:
+data sym_local
+
+.section .data.unaligned_hidden
+unaligned_hidden:
+data sym_hidden
+
+.section .data.unaligned_global
+unaligned_global:
+data sym_global
+
+.section .data.unaligned_DYNAMIC
+unaligned_DYNAMIC:
+data _DYNAMIC
+
+.section .data.aligned_local
+.p2align 1
+aligned_local:
+data sym_local
+
+.section .data.aligned_hidden
+.p2align 1
+aligned_hidden:
+data sym_hidden
+
+.section .data.aligned_global
+.p2align 1
+aligned_global:
+data sym_global
+
+.section .data.aligned_global_abs
+.p2align 1
+aligned_global_abs:
+data sym_global_abs
+
+.section .data.aligned_weak_undef
+.p2align 1
+aligned_weak_undef:
+data sym_weak_undef
+
+.section .data.aligned_DYNAMIC
+.p2align 1
+aligned_DYNAMIC:
+data _DYNAMIC
diff --git a/ld/testsuite/ld-riscv-elf/relr-discard-pic.d b/ld/testsuite/ld-riscv-elf/relr-discard-pic.d
new file mode 100644
index 00000000000..d45420b93bd
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-discard-pic.d
@@ -0,0 +1,14 @@
+#source: discard.s
+#as: -march=rv64i
+#ld: -shared -T discard.ld -melf64lriscv -z pack-relative-relocs
+#readelf: -rW
+
+Relocation section '\.rela\.dyn'.*
+[ ]+Offset[ ]+Info[ ]+Type.*
+0000000000020018[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000001000c[ ]+sym_global \+ 0
+0000000000020020[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000001000c[ ]+sym_global_keep \+ 0
+
+Relocation section '\.relr\.dyn'.*
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000000020008[ ]+0000000000020008[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x8
+0001:[ ]+0000000000000003[ ]+0000000000020010[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x10
diff --git a/ld/testsuite/ld-riscv-elf/relr-discard-pie.d b/ld/testsuite/ld-riscv-elf/relr-discard-pie.d
new file mode 100644
index 00000000000..1137a7de56e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-discard-pie.d
@@ -0,0 +1,11 @@
+#source: discard.s
+#as: -march=rv64i
+#ld: -pie -T discard.ld -melf64lriscv -z pack-relative-relocs
+#readelf: -rW
+
+Relocation section '\.relr\.dyn'.*
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000000020008[ ]+0000000000020008[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x8
+0001:[ ]+000000000000000f[ ]+0000000000020010[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x10
+[ ]+0000000000020018[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x18
+[ ]+0000000000020020[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x20
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.d b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.d
new file mode 100644
index 00000000000..843953f3d38
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.d
@@ -0,0 +1,21 @@
+#...
+Contents of section .got:
+ 20000 00003412 30000100 34000100 00003412.*
+ 20010 00000000 00000000.*
+#...
+Disassembly of section .text:
+
+00010000 <_start>:
+[ ]+10000:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10004:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20004 <.*>
+[ ]+10008:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20008 <.*>
+[ ]+10010:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10014:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20010 <.*>
+[ ]+10018:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20014 <.*>
+[ ]+10020:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10024:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20018 <.*>
+[ ]+10028:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 2000c <.*>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.rd b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.rd
new file mode 100644
index 00000000000..22a8888ade1
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pic.rd
@@ -0,0 +1,11 @@
+Relocation section '\.rela\.dyn'.*contains 3 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+00020010[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+00010038[ ]+sym_global \+ 0
+00020014[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+0000002a[ ]+sym_global_abs \+ 0
+00020018[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+00000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 3 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+00020004[ ]+00020004[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x4
+0001:[ ]+00000007[ ]+00020008[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x8
+[ ]+0002000c[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0xc
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.d b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.d
new file mode 100644
index 00000000000..432620d4395
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.d
@@ -0,0 +1,21 @@
+#...
+Contents of section .got:
+ 20000 00003412 30000100 34000100 00003412.*
+ 20010 38000100 2a000000.*
+#...
+Disassembly of section .text:
+
+00010000 <_start>:
+[ ]+10000:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10004:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20004 <.*>
+[ ]+10008:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20008 <.*>
+[ ]+10010:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10014:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20010 <.*>
+[ ]+10018:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20014 <.*>
+[ ]+10020:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10024:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20018 <.*>
+[ ]+10028:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 2000c <.*>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.rd b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.rd
new file mode 100644
index 00000000000..b0138b16139
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv32-pie.rd
@@ -0,0 +1,11 @@
+Relocation section '\.rela\.dyn'.*contains 2 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+00000000[ ]+[0-9a-f]+[ ]+R_RISCV_NONE[ ]+0
+00020018[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+00000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 4 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+00020004[ ]+00020004[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x4
+0001:[ ]+0000000f[ ]+00020008[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x8
+[ ]+0002000c[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0xc
+[ ]+00020010[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x10
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.d b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.d
new file mode 100644
index 00000000000..30216ede4c4
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.d
@@ -0,0 +1,23 @@
+#...
+Contents of section .got:
+ 20000 00003412 00000000 30000100 00000000.*
+ 20010 34000100 00000000 00003412 00000000.*
+ 20020 00000000 00000000 00000000 00000000.*
+ 20030 00000000 00000000.*
+#...
+Disassembly of section .text:
+
+0000000000010000 <_start>:
+[ ]+10000:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10004:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20008 <.*>
+[ ]+10008:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20010 <.*>
+[ ]+10010:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10014:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20020 <.*>
+[ ]+10018:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20028 <.*>
+[ ]+10020:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10024:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20030 <.*>
+[ ]+10028:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20018 <.*>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.rd b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.rd
new file mode 100644
index 00000000000..39d4dc999f4
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pic.rd
@@ -0,0 +1,11 @@
+Relocation section '\.rela\.dyn'.*contains 3 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+0000000000020020[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+0000000000010038[ ]+sym_global \+ 0
+0000000000020028[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+000000000000002a[ ]+sym_global_abs \+ 0
+0000000000020030[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+0000000000000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 3 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000000020008[ ]+0000000000020008[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x8
+0001:[ ]+0000000000000007[ ]+0000000000020010[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x10
+[ ]+0000000000020018[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x18
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.d b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.d
new file mode 100644
index 00000000000..43da91dfb29
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.d
@@ -0,0 +1,23 @@
+#...
+Contents of section .got:
+ 20000 00003412 00000000 30000100 00000000.*
+ 20010 34000100 00000000 00003412 00000000.*
+ 20020 38000100 00000000 2a000000 00000000.*
+ 20030 00000000 00000000.*
+#...
+Disassembly of section .text:
+
+0000000000010000 <_start>:
+[ ]+10000:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10004:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20008 <.*>
+[ ]+10008:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20010 <.*>
+[ ]+10010:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10014:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20020 <.*>
+[ ]+10018:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20028 <.*>
+[ ]+10020:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10024:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20030 <.*>
+[ ]+10028:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20018 <.*>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.rd b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.rd
new file mode 100644
index 00000000000..6776d438cb3
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got-rv64-pie.rd
@@ -0,0 +1,11 @@
+Relocation section '\.rela\.dyn'.*contains 2 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+0000000000000000[ ]+[0-9a-f]+[ ]+R_RISCV_NONE[ ]+0
+0000000000020030[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+0000000000000000[ ]+sym_weak_undef \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 4 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0000000000020008[ ]+0000000000020008[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x8
+0001:[ ]+000000000000000f[ ]+0000000000020010[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x10
+[ ]+0000000000020018[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x18
+[ ]+0000000000020020[ ]+_GLOBAL_OFFSET_TABLE_ \+ 0x20
diff --git a/ld/testsuite/ld-riscv-elf/relr-got.s b/ld/testsuite/ld-riscv-elf/relr-got.s
new file mode 100644
index 00000000000..5f98340b5b6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-got.s
@@ -0,0 +1,31 @@
+# Test GOT relocations with DT_RELR.
+
+.text
+.option norelax
+.option pic
+.global _start
+_start:
+ la x1, sym_local
+ la x1, sym_hidden
+ la x1, sym_global
+ la x1, sym_global_abs
+ la x1, sym_weak_undef
+ la x1, _DYNAMIC
+
+sym_local:
+ nop
+
+.global sym_hidden
+.hidden sym_hidden
+sym_hidden:
+ nop
+
+.global sym_global
+sym_global:
+ nop
+
+.global sym_global_abs
+.set sym_global_abs, 42
+
+.global sym_weak_undef
+.weak sym_weak_undef
diff --git a/ld/testsuite/ld-riscv-elf/relr-relocs.ld b/ld/testsuite/ld-riscv-elf/relr-relocs.ld
new file mode 100644
index 00000000000..2010568190e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-relocs.ld
@@ -0,0 +1,23 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = 0x8000); . = 0x10000;
+ .text :
+ {
+ *(.before)
+ *(.text)
+ *(.after)
+ } =0
+ . = 0x20000;
+ .got : { *(.got) *(.got.plt)}
+ . = 0x12340000;
+ .far : { *(.far) }
+ .riscv.attributes 0 : { *(.ARM.atttributes) }
+ /* Providing a .data section triggers a non-executable segment to be
+ generated, which gives somewhere else for the linker to put the TLS
+ segment without creating a RWX permissioned one. */
+ .data : { *(.data) }
+}
diff --git a/ld/testsuite/ld-riscv-elf/relr-text-pic.d b/ld/testsuite/ld-riscv-elf/relr-text-pic.d
new file mode 100644
index 00000000000..bc151e2f128
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-text-pic.d
@@ -0,0 +1,14 @@
+#source: relr-text.s
+#ld: -shared -z pack-relative-relocs -T relr-relocs.ld
+#readelf: -drW
+
+#...
+.*\(TEXTREL\)[ ]+0x0
+#...
+.*\(RELR\).*
+.*\(RELRSZ\)[ ]+(4|8) \(bytes\)
+.*\(RELRENT\)[ ]+(4|8) \(bytes\)
+#...
+Relocation section '\.relr\.dyn' .* contains 1 entry which relocates 1 location:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+(00000000|)00010000[ ]+(00000000|)00010000[ ]+_start
diff --git a/ld/testsuite/ld-riscv-elf/relr-text-pie.d b/ld/testsuite/ld-riscv-elf/relr-text-pie.d
new file mode 100644
index 00000000000..65ef1de775f
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-text-pie.d
@@ -0,0 +1,14 @@
+#source: relr-text.s
+#ld: -pie -z pack-relative-relocs -T relr-relocs.ld
+#readelf: -drW
+
+#...
+.*\(TEXTREL\)[ ]+0x0
+#...
+.*\(RELR\).*
+.*\(RELRSZ\)[ ]+(4|8) \(bytes\)
+.*\(RELRENT\)[ ]+(4|8) \(bytes\)
+#...
+Relocation section '\.relr\.dyn' .* contains 1 entry which relocates 1 location:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+(00000000|)00010000[ ]+(00000000|)00010000[ ]+_start
diff --git a/ld/testsuite/ld-riscv-elf/relr-text.s b/ld/testsuite/ld-riscv-elf/relr-text.s
new file mode 100644
index 00000000000..7e0eecbc527
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relr-text.s
@@ -0,0 +1,10 @@
+# Test DT_RELR with DT_TEXTREL.
+
+.text
+.p2align 3
+.global _start
+_start:
+.global foo
+.hidden foo
+foo:
+.quad foo
--
2.39.5 (Apple Git-154)
More information about the Binutils
mailing list