@@ -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. */
@@ -205,6 +211,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"
@@ -246,6 +285,17 @@ struct riscv_elf_link_hash_table
bool (*make_plt_header) (bfd *output_bfd, struct riscv_elf_link_hash_table *htab);
bool (*make_plt_entry) (bfd *output_bfd, asection *got, bfd_vma got_offset,
asection *plt, bfd_vma plt_offset);
+
+ /* 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. */
@@ -1692,6 +1742,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)
{
@@ -1841,6 +2254,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. */
@@ -1870,6 +2304,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. */
@@ -2918,7 +3361,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
/* We need to generate a R_RISCV_RELATIVE relocation later in the
riscv_elf_finish_dynamic_symbol if h->dynindx != -1; Otherwise,
generate a R_RISCV_RELATIVE relocation here now. */
- if (relative_got)
+ if (relative_got && !info->enable_dt_relr)
{
asection *s = htab->elf.srelgot;
BFD_ASSERT (s != NULL);
@@ -3155,8 +3598,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;
@@ -3196,6 +3640,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. */
@@ -3642,6 +4094,11 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
of a version file. The entry in the global offset table will
already have been initialized in the relocate_section function. */
BFD_ASSERT ((h->got.offset & 1) != 0);
+
+ /* 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
@@ -3678,6 +4135,8 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
}
}
+ skip_got_reloc:
+
if (h->needs_copy)
{
Elf_Internal_Rela rela;
@@ -4762,6 +5221,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;
}
@@ -5398,7 +5867,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
@@ -6007,6 +6479,7 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd,
#define bfd_elfNN_mkobject elfNN_riscv_mkobject
#define bfd_elfNN_get_synthetic_symtab \
elfNN_riscv_get_synthetic_symtab
+#define bfd_elfNN_new_section_hook elfNN_riscv_new_section_hook
#define elf_backend_reloc_type_class riscv_reloc_type_class
#define elf_backend_copy_indirect_symbol riscv_elf_copy_indirect_symbol
@@ -6035,6 +6508,8 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd,
elfNN_riscv_link_setup_gnu_properties
#define elf_backend_merge_gnu_properties \
elfNN_riscv_merge_gnu_properties
+#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_can_gc_sections 1
#define elf_backend_can_refcount 1
@@ -1679,6 +1679,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)
{
@@ -1687,6 +1701,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;
}
@@ -469,7 +469,8 @@ proc supports_dt_relr {} {
|| [istarget i?86-*-*]
|| [istarget powerpc64*-*-*]
|| [istarget aarch64*-*-*]
- || [istarget loongarch64*-*-*])
+ || [istarget loongarch64*-*-*]
+ || [istarget riscv*-*-*])
&& ([istarget *-*-linux*]
|| [istarget *-*-gnu*]) } {
return 1
@@ -23,6 +23,7 @@ case "$target" in
*)
GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes
+ source_sh ${srcdir}/emulparams/dt-relr.sh
;;
esac
@@ -6,4 +6,4 @@
Relocation section '\.rela\.dyn'.*
[ ]+Offset[ ]+Info[ ]+Type.*
0+0[ ]+0+0[ ]+R_RISCV_NONE[ ]+0
-0+(20008|20010)[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+0+10008[ ]+sym_global \+ 0
+0+(20008|20010)[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+0+1000c[ ]+sym_global \+ 0
@@ -8,6 +8,6 @@ SECTIONS
.text : { *(.text) }
. = 0x20000;
.got : { *(.got) *(.got.plt)}
- . = 0x30000;
+ . = 0x12340000;
.data : { *(.data) *(.data.*) }
}
@@ -9,15 +9,15 @@ _start:
sym_local:
nop
-.global sym_global
-sym_global:
- 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
@@ -39,16 +39,16 @@ sym_hidden:
discard_local:
.quad sym_local
-.section .discard.global,"a"
-.p2align 1
-discard_global:
-.quad sym_global
-
.section .discard.hidden,"a"
.p2align 1
discard_hidden:
.quad sym_hidden
+.section .discard.global,"a"
+.p2align 1
+discard_global:
+.quad sym_global
+
.section .discard.global_abs,"a"
.p2align 1
discard_global_abs:
@@ -78,6 +78,40 @@ 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
@@ -242,6 +276,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-textrel-pie"
+ run_dump_test "relr-textrel-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
new file mode 100644
@@ -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.*
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -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.*
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -0,0 +1,87 @@
+# Test symbol references in .data when used with DT_RELR.
+# Relocations for unaligned sections are currently not packed.
+
+.text
+.option pic
+.option norvc
+.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
+
+# data macro
+
+.macro data value
+.ifdef __64_bit__
+ .quad \value
+.else
+ .long \value
+.endif
+.endm
+
+# unaligned data
+
+.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
+
+# aligned data
+
+.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
new file mode 100644
@@ -0,0 +1,12 @@
+#source: discard.s
+#as:
+#ld: -shared -Tdiscard.ld -z pack-relative-relocs
+#readelf: -rW
+
+Relocation section '\.rela\.dyn'.*
+[ ]+Offset[ ]+Info[ ]+Type.*
+0+(20008|20010)[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+0+1000c[ ]+sym_global \+ 0
+
+Relocation section '\.relr\.dyn'.*contains 1 entry which relocates 1 location:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0+(20004|20008)[ ]+0+(20004|20008)[ ]+_GLOBAL_OFFSET_TABLE_ \+ (0x4|0x8)
new file mode 100644
@@ -0,0 +1,9 @@
+#source: discard.s
+#as:
+#ld: -pie -Tdiscard.ld -z pack-relative-relocs
+#readelf: -rW
+
+Relocation section '\.relr\.dyn'.*contains 2 entries which relocate 2 locations:
+Index:[ ]+Entry[ ]+Address[ ]+Symbolic Address
+0000:[ ]+0+(20004|20008)[ ]+0+(20004|20008)[ ]+_GLOBAL_OFFSET_TABLE_ \+ (0x4|0x8)
+0001:[ ]+0+3[ ]+0+(20008|20010)[ ]+_GLOBAL_OFFSET_TABLE_ \+ (0x8|0x10)
new file mode 100644
@@ -0,0 +1,41 @@
+#...
+Contents of section .got:
+ 20000 00003412 00000100 04000100 00003412.*
+ 20010 00000000 00000000 00000000.*
+#...
+Disassembly of section .text.got_local:
+
+0001000c <.text.got_local>:
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10010:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20004 <.*>
+
+Disassembly of section .text.got_hidden:
+
+00010014 <.text.got_hidden>:
+[ ]+10014:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10018:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20008 <.*>
+
+Disassembly of section .text.got_global:
+
+0001001c <.text.got_global>:
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10020:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20010 <.*>
+
+Disassembly of section .text.got_global_abs:
+
+00010024 <.text.got_global_abs>:
+[ ]+10024:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10028:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20014 <.*>
+
+Disassembly of section .text.got_weak_undef:
+
+0001002c <.text.got_weak_undef>:
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10030:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20018 <.*>
+
+Disassembly of section .text.got_DYNAMIC:
+
+00010034 <.text.got_DYNAMIC>:
+[ ]+10034:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10038:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 2000c <.*>
+#...
new file mode 100644
@@ -0,0 +1,11 @@
+Relocation section '\.rela\.dyn'.*contains 3 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+00020010[ ]+[0-9a-f]+[ ]+R_RISCV_32[ ]+00010008[ ]+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
new file mode 100644
@@ -0,0 +1,41 @@
+#...
+Contents of section .got:
+ 20000 00003412 00000100 04000100 00003412.*
+ 20010 08000100 2a000000 00000000.*
+#...
+Disassembly of section .text.got_local:
+
+0001000c <.text.got_local>:
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10010:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20004 <.*>
+
+Disassembly of section .text.got_hidden:
+
+00010014 <.text.got_hidden>:
+[ ]+10014:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10018:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20008 <.*>
+
+Disassembly of section .text.got_global:
+
+0001001c <.text.got_global>:
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10020:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20010 <.*>
+
+Disassembly of section .text.got_global_abs:
+
+00010024 <.text.got_global_abs>:
+[ ]+10024:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10028:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20014 <.*>
+
+Disassembly of section .text.got_weak_undef:
+
+0001002c <.text.got_weak_undef>:
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10030:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 20018 <.*>
+
+Disassembly of section .text.got_DYNAMIC:
+
+00010034 <.text.got_DYNAMIC>:
+[ ]+10034:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10038:[ ]+[0-9a-f]+[ ]+lw[ ]+.*# 2000c <.*>
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -0,0 +1,43 @@
+#...
+Contents of section .got:
+ 20000 00003412 00000000 00000100 00000000.*
+ 20010 04000100 00000000 00003412 00000000.*
+ 20020 00000000 00000000 00000000 00000000.*
+ 20030 00000000 00000000.*
+#...
+Disassembly of section .text.got_local:
+
+000000000001000c <.text.got_local>:
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10010:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20008 <.*>
+
+Disassembly of section .text.got_hidden:
+
+0000000000010014 <.text.got_hidden>:
+[ ]+10014:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10018:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20010 <.*>
+
+Disassembly of section .text.got_global:
+
+000000000001001c <.text.got_global>:
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10020:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20020 <.*>
+
+Disassembly of section .text.got_global_abs:
+
+0000000000010024 <.text.got_global_abs>:
+[ ]+10024:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10028:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20028 <.*>
+
+Disassembly of section .text.got_weak_undef:
+
+000000000001002c <.text.got_weak_undef>:
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10030:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20030 <.*>
+
+Disassembly of section .text.got_DYNAMIC:
+
+0000000000010034 <.text.got_DYNAMIC>:
+[ ]+10034:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10038:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20018 <.*>
+#...
new file mode 100644
@@ -0,0 +1,11 @@
+Relocation section '\.rela\.dyn'.*contains 3 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+0000000000020020[ ]+[0-9a-f]+[ ]+R_RISCV_64[ ]+0000000000010008[ ]+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
new file mode 100644
@@ -0,0 +1,43 @@
+#...
+Contents of section .got:
+ 20000 00003412 00000000 00000100 00000000.*
+ 20010 04000100 00000000 00003412 00000000.*
+ 20020 08000100 00000000 2a000000 00000000.*
+ 20030 00000000 00000000.*
+#...
+Disassembly of section .text.got_local:
+
+000000000001000c <.text.got_local>:
+[ ]+1000c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10010:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20008 <.*>
+
+Disassembly of section .text.got_hidden:
+
+0000000000010014 <.text.got_hidden>:
+[ ]+10014:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10018:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20010 <.*>
+
+Disassembly of section .text.got_global:
+
+000000000001001c <.text.got_global>:
+[ ]+1001c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10020:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20020 <.*>
+
+Disassembly of section .text.got_global_abs:
+
+0000000000010024 <.text.got_global_abs>:
+[ ]+10024:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10028:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20028 <.*>
+
+Disassembly of section .text.got_weak_undef:
+
+000000000001002c <.text.got_weak_undef>:
+[ ]+1002c:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10030:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20030 <.*>
+
+Disassembly of section .text.got_DYNAMIC:
+
+0000000000010034 <.text.got_DYNAMIC>:
+[ ]+10034:[ ]+[0-9a-f]+[ ]+auipc.*
+[ ]+10038:[ ]+[0-9a-f]+[ ]+ld[ ]+.*# 20018 <.*>
+#...
new file mode 100644
@@ -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
new file mode 100644
@@ -0,0 +1,43 @@
+# Test GOT relocations with DT_RELR.
+
+.text
+.option norelax
+.option pic
+.global _start
+_start:
+
+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 .text.got_local, "ax"
+ la x1, sym_local
+
+.section .text.got_hidden, "ax"
+ la x1, sym_hidden
+
+.section .text.got_global, "ax"
+ la x1, sym_global
+
+.section .text.got_global_abs, "ax"
+ la x1, sym_global_abs
+
+.section .text.got_weak_undef, "ax"
+ la x1, sym_weak_undef
+
+.section .text.got_DYNAMIC, "ax"
+ la x1, _DYNAMIC
new file mode 100644
@@ -0,0 +1,12 @@
+OUTPUT_ARCH (riscv)
+ENTRY (_start)
+SECTIONS
+{
+ . = 0x10000;
+ .text : { *(.got_*) *(.text)}
+ . = 0x20000;
+ .got : { *(.got) *(.got.plt)}
+ . = 0x12340000;
+ .data : { *(.data) }
+ .riscv.attributes 0 : { *(.riscv.atttributes) }
+}
new file mode 100644
@@ -0,0 +1,14 @@
+#source: relr-textrel.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
new file mode 100644
@@ -0,0 +1,14 @@
+#source: relr-textrel.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
new file mode 100644
@@ -0,0 +1,10 @@
+# Test DT_RELR with DT_TEXTREL.
+
+.text
+.p2align 3
+.global _start
+_start:
+.global foo
+.hidden foo
+foo:
+.quad foo