diff options
63 files changed, 1523 insertions, 53 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a7e0cae..b0cd8b8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,39 @@ +2020-10-16 Nelson Chu <nelson.chu@sifive.com> + + * elfnn-riscv.c: Include "objalloc.h" since we need objalloc_alloc. + (riscv_elf_link_hash_table): Add loc_hash_table and loc_hash_memory + for local STT_GNU_IFUNC symbols. + (riscv_elf_got_plt_val): Removed. + (riscv_elf_local_htab_hash, riscv_elf_local_htab_eq): New functions. + Use to compare local hash entries. + (riscv_elf_get_local_sym_hash): New function. Find a hash entry for + local symbol, and create a new one if needed. + (riscv_elf_link_hash_table_free): New function. Destroy an riscv + elf linker hash table. + (riscv_elf_link_hash_table_create): Create hash table for local ifunc. + (riscv_elf_check_relocs): Create a fake global symbol to track the + local ifunc symbol. Add support to check and handle the relocations + reference to ifunc symbols. + (allocate_dynrelocs): Let allocate_ifunc_dynrelocs and + allocate_local_ifunc_dynrelocs to handle the ifunc symbols if they + are defined and referenced in a non-shared object. + (allocate_ifunc_dynrelocs): New function. Allocate space in .plt, + .got and associated reloc sections for ifunc dynamic relocs. + (allocate_local_ifunc_dynrelocs): Likewise, but for local ifunc + dynamic relocs. + (riscv_elf_relocate_section): Add support to handle the relocation + referenced to ifunc symbols. + (riscv_elf_size_dynamic_sections): Updated. + (riscv_elf_adjust_dynamic_symbol): Updated. + (riscv_elf_finish_dynamic_symbol): Finish up the ifunc handling, + including fill the PLT and GOT entries for ifunc symbols. + (riscv_elf_finish_local_dynamic_symbol): New function. Called by + riscv_elf_finish_dynamic_symbol to handle the local ifunc symbols. + (_bfd_riscv_relax_section): Don't do the relaxation for ifunc. + * elfxx-riscv.c: Add R_RISCV_IRELATIVE. + * configure.ac: Link elf-ifunc.lo to use the generic ifunc support. + * configure: Regenerated. + 2020-10-16 Alan Modra <amodra@gmail.com> * elf32-arc.c (replace_func): Correct return type. diff --git a/bfd/configure b/bfd/configure index 636f338..5d84aed 100755 --- a/bfd/configure +++ b/bfd/configure @@ -14917,8 +14917,8 @@ do powerpc_elf64_fbsd_le_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf" target_size=64 ;; powerpc_xcoff_vec) tb="$tb coff-rs6000.lo $xcoff" ;; pru_elf32_vec) tb="$tb elf32-pru.lo elf32.lo $elf" ;; - riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf32.lo $elf" ;; - riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf32.lo $elf"; target_size=64 ;; + riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;; + riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;; rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;; rs6000_xcoff64_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; rs6000_xcoff64_aix_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index cecb0fb..5ec4d4f 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -623,8 +623,8 @@ do powerpc_elf64_fbsd_le_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf" target_size=64 ;; powerpc_xcoff_vec) tb="$tb coff-rs6000.lo $xcoff" ;; pru_elf32_vec) tb="$tb elf32-pru.lo elf32.lo $elf" ;; - riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf32.lo $elf" ;; - riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf32.lo $elf"; target_size=64 ;; + riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;; + riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;; rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;; rs6000_xcoff64_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; rs6000_xcoff64_aix_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index c088278..a26cd3f 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -31,6 +31,7 @@ #include "elfxx-riscv.h" #include "elf/riscv.h" #include "opcode/riscv.h" +#include "objalloc.h" /* Internal relocations used exclusively by the relaxation pass. */ #define R_RISCV_DELETE (R_RISCV_max + 1) @@ -115,6 +116,10 @@ struct riscv_elf_link_hash_table /* The max alignment of output sections. */ bfd_vma max_alignment; + + /* Used by local STT_GNU_IFUNC symbols. */ + htab_t loc_hash_table; + void * loc_hash_memory; }; @@ -153,17 +158,13 @@ riscv_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) #define GOT_ENTRY_SIZE RISCV_ELF_WORD_BYTES +/* Reserve two entries of GOTPLT for ld.so, one is used for PLT resolver, + the other is used for link map. Other targets also reserve one more + entry used for runtime profile? */ #define GOTPLT_HEADER_SIZE (2 * GOT_ENTRY_SIZE) #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset) -static bfd_vma -riscv_elf_got_plt_val (bfd_vma plt_index, struct bfd_link_info *info) -{ - return sec_addr (riscv_elf_hash_table (info)->elf.sgotplt) - + GOTPLT_HEADER_SIZE + (plt_index * GOT_ENTRY_SIZE); -} - #if ARCH_SIZE == 32 # define MATCH_LREG MATCH_LW #else @@ -265,6 +266,86 @@ link_hash_newfunc (struct bfd_hash_entry *entry, return entry; } +/* Compute a hash of a local hash entry. We use elf_link_hash_entry + for local symbol so that we can handle local STT_GNU_IFUNC symbols + as global symbol. We reuse indx and dynstr_index for local symbol + hash since they aren't used by global symbols in this backend. */ + +static hashval_t +riscv_elf_local_htab_hash (const void *ptr) +{ + struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr; + return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index); +} + +/* Compare local hash entries. */ + +static int +riscv_elf_local_htab_eq (const void *ptr1, const void *ptr2) +{ + struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1; + struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2; + + return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index; +} + +/* Find and/or create a hash entry for local symbol. */ + +static struct elf_link_hash_entry * +riscv_elf_get_local_sym_hash (struct riscv_elf_link_hash_table *htab, + bfd *abfd, const Elf_Internal_Rela *rel, + bfd_boolean create) +{ + struct riscv_elf_link_hash_entry eh, *ret; + asection *sec = abfd->sections; + hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, + ELFNN_R_SYM (rel->r_info)); + void **slot; + + eh.elf.indx = sec->id; + eh.elf.dynstr_index = ELFNN_R_SYM (rel->r_info); + slot = htab_find_slot_with_hash (htab->loc_hash_table, &eh, h, + create ? INSERT : NO_INSERT); + + if (!slot) + return NULL; + + if (*slot) + { + ret = (struct riscv_elf_link_hash_entry *) *slot; + return &ret->elf; + } + + ret = (struct riscv_elf_link_hash_entry *) + objalloc_alloc ((struct objalloc *) htab->loc_hash_memory, + sizeof (struct riscv_elf_link_hash_entry)); + if (ret) + { + memset (ret, 0, sizeof (*ret)); + ret->elf.indx = sec->id; + ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info); + ret->elf.dynindx = -1; + *slot = ret; + } + return &ret->elf; +} + +/* Destroy a RISC-V elf linker hash table. */ + +static void +riscv_elf_link_hash_table_free (bfd *obfd) +{ + struct riscv_elf_link_hash_table *ret + = (struct riscv_elf_link_hash_table *) obfd->link.hash; + + if (ret->loc_hash_table) + htab_delete (ret->loc_hash_table); + if (ret->loc_hash_memory) + objalloc_free ((struct objalloc *) ret->loc_hash_memory); + + _bfd_elf_link_hash_table_free (obfd); +} + /* Create a RISC-V ELF linker hash table. */ static struct bfd_link_hash_table * @@ -286,6 +367,20 @@ riscv_elf_link_hash_table_create (bfd *abfd) } ret->max_alignment = (bfd_vma) -1; + + /* Create hash table for local ifunc. */ + ret->loc_hash_table = htab_try_create (1024, + riscv_elf_local_htab_hash, + riscv_elf_local_htab_eq, + NULL); + ret->loc_hash_memory = objalloc_create (); + if (!ret->loc_hash_table || !ret->loc_hash_memory) + { + riscv_elf_link_hash_table_free (abfd); + return NULL; + } + ret->elf.root.hash_table_free = riscv_elf_link_hash_table_free; + return &ret->elf.root; } @@ -477,6 +572,9 @@ bad_static_reloc (bfd *abfd, unsigned r_type, struct elf_link_hash_entry *h) { reloc_howto_type * r = riscv_elf_rtype_to_howto (abfd, r_type); + /* We propably can improve the information to tell users that they + should be recompile the code with -fPIC or -fPIE, just like what + x86 does. */ (*_bfd_error_handler) (_("%pB: relocation %s against `%s' can not be used when making a shared " "object; recompile with -fPIC"), @@ -526,7 +624,32 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } if (r_symndx < symtab_hdr->sh_info) - h = NULL; + { + /* A local symbol. */ + Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, + abfd, r_symndx); + if (isym == NULL) + return FALSE; + + /* Check relocation against local STT_GNU_IFUNC symbol. */ + if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) + { + h = riscv_elf_get_local_sym_hash (htab, abfd, rel, TRUE); + if (h == NULL) + return FALSE; + + /* Fake STT_GNU_IFUNC global symbol. */ + h->root.root.string = bfd_elf_sym_name (abfd, symtab_hdr, + isym, NULL); + h->type = STT_GNU_IFUNC; + h->def_regular = 1; + h->ref_regular = 1; + h->forced_local = 1; + h->root.type = bfd_link_hash_defined; + } + else + h = NULL; + } else { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; @@ -535,6 +658,32 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h = (struct elf_link_hash_entry *) h->root.u.i.link; } + if (h != NULL) + { + switch (r_type) + { + case R_RISCV_32: + case R_RISCV_64: + case R_RISCV_CALL: + case R_RISCV_CALL_PLT: + case R_RISCV_HI20: + case R_RISCV_GOT_HI20: + case R_RISCV_PCREL_HI20: + /* Create the ifunc sections, iplt and ipltgot, for static + executables. */ + if (h->type == STT_GNU_IFUNC + && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) + return FALSE; + break; + + default: + break; + } + + /* It is referenced by a non-shared object. */ + h->ref_regular = 1; + } + switch (r_type) { case R_RISCV_TLS_GD_HI20: @@ -574,12 +723,26 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h->plt.refcount += 1; break; + case R_RISCV_PCREL_HI20: + if (h != NULL + && h->type == STT_GNU_IFUNC) + { + h->non_got_ref = 1; + h->pointer_equality_needed = 1; + + /* We don't use the PCREL_HI20 in the data section, + so we always need the plt when it refers to + ifunc symbol. */ + h->plt.refcount += 1; + } + /* Fall through. */ + case R_RISCV_JAL: case R_RISCV_BRANCH: case R_RISCV_RVC_BRANCH: case R_RISCV_RVC_JUMP: - case R_RISCV_PCREL_HI20: - /* In shared libraries, these relocs are known to bind locally. */ + /* In shared libraries and pie, these relocs are known + to bind locally. */ if (bfd_link_pic (info)) break; goto static_reloc; @@ -604,15 +767,23 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, /* Fall through. */ static_reloc: - /* This reloc might not bind locally. */ - if (h != NULL) - h->non_got_ref = 1; - if (h != NULL && !bfd_link_pic (info)) + if (h != NULL + && (!bfd_link_pic (info) + || h->type == STT_GNU_IFUNC)) { - /* We may need a .plt entry if the function this reloc - refers to is in a shared lib. */ - h->plt.refcount += 1; + /* This reloc might not bind locally. */ + h->non_got_ref = 1; + h->pointer_equality_needed = 1; + + if (!h->def_regular + || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) + { + /* We may need a .plt entry if the symbol is a function + defined in a shared lib or is a function referenced + from the code or read-only section. */ + h->plt.refcount += 1; + } } /* If we are creating a shared library, and this is a reloc @@ -635,21 +806,28 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, If on the other hand, we are creating an executable, we may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the - symbol. */ + symbol. + + Generate dynamic pointer relocation against STT_GNU_IFUNC + symbol in the non-code section (R_RISCV_32/R_RISCV_64). */ reloc_howto_type * r = riscv_elf_rtype_to_howto (abfd, r_type); if ((bfd_link_pic (info) && (sec->flags & SEC_ALLOC) != 0 - && ((r != NULL && ! r->pc_relative) + && ((r != NULL && !r->pc_relative) || (h != NULL - && (! info->symbolic + && (!info->symbolic || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (!bfd_link_pic (info) && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (h->root.type == bfd_link_hash_defweak - || !h->def_regular))) + || !h->def_regular)) + || (!bfd_link_pic (info) + && h != NULL + && h->type == STT_GNU_IFUNC + && (sec->flags & SEC_CODE) == 0)) { struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; @@ -786,9 +964,10 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt) { if (h->plt.refcount <= 0 - || SYMBOL_CALLS_LOCAL (info, h) - || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT - && h->root.type == bfd_link_hash_undefweak)) + || (h->type != STT_GNU_IFUNC + && (SYMBOL_CALLS_LOCAL (info, h) + || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + && h->root.type == bfd_link_hash_undefweak)))) { /* This case can occur if we saw a R_RISCV_CALL_PLT reloc in an input file, but the symbol was never referred to by a dynamic @@ -901,8 +1080,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab = riscv_elf_hash_table (info); BFD_ASSERT (htab != NULL); - if (htab->elf.dynamic_sections_created - && h->plt.refcount > 0) + /* Since STT_GNU_IFUNC symbols must go through PLT, we handle them + in the allocate_ifunc_dynrelocs and allocate_local_ifunc_dynrelocs, + if they are defined and referenced in a non-shared object. */ + if (h->type == STT_GNU_IFUNC + && h->def_regular) + return TRUE; + else if (htab->elf.dynamic_sections_created + && h->plt.refcount > 0) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -1088,6 +1273,55 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return TRUE; } +/* Allocate space in .plt, .got and associated reloc sections for + ifunc dynamic relocs. */ + +static bfd_boolean +allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, + void *inf) +{ + struct bfd_link_info *info; + + if (h->root.type == bfd_link_hash_indirect) + return TRUE; + + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + info = (struct bfd_link_info *) inf; + + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it + here if it is defined and referenced in a non-shared object. */ + if (h->type == STT_GNU_IFUNC + && h->def_regular) + return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, + &h->dyn_relocs, + PLT_ENTRY_SIZE, + PLT_HEADER_SIZE, + GOT_ENTRY_SIZE, + TRUE); + return TRUE; +} + +/* Allocate space in .plt, .got and associated reloc sections for + local ifunc dynamic relocs. */ + +static bfd_boolean +allocate_local_ifunc_dynrelocs (void **slot, void *inf) +{ + struct elf_link_hash_entry *h + = (struct elf_link_hash_entry *) *slot; + + if (h->type != STT_GNU_IFUNC + || !h->def_regular + || !h->ref_regular + || !h->forced_local + || h->root.type != bfd_link_hash_defined) + abort (); + + return allocate_ifunc_dynrelocs (h, inf); +} + static bfd_boolean riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { @@ -1178,10 +1412,18 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) } } - /* Allocate global sym .plt and .got entries, and space for global - sym dynamic relocs. */ + /* Allocate .plt and .got entries and space dynamic relocs for + global symbols. */ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); + /* Allocate .plt and .got entries and space dynamic relocs for + global ifunc symbols. */ + elf_link_hash_traverse (&htab->elf, allocate_ifunc_dynrelocs, info); + + /* Allocate .plt and .got entries and space dynamic relocs for + local ifunc symbols. */ + htab_traverse (htab->loc_hash_table, allocate_local_ifunc_dynrelocs, info); + if (htab->elf.sgotplt) { struct elf_link_hash_entry *got; @@ -1213,6 +1455,8 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) if (s == htab->elf.splt || s == htab->elf.sgot || s == htab->elf.sgotplt + || s == htab->elf.iplt + || s == htab->elf.igotplt || s == htab->elf.sdynbss || s == htab->elf.sdynrelro || s == htab->sdyntdata) @@ -1645,7 +1889,6 @@ riscv_elf_relocate_section (bfd *output_bfd, Elf_Internal_Rela *relend; riscv_pcrel_relocs pcrel_relocs; bfd_boolean ret = FALSE; - asection *sreloc = elf_section_data (input_section)->sreloc; 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); @@ -1664,7 +1907,7 @@ riscv_elf_relocate_section (bfd *output_bfd, asection *sec; bfd_vma relocation; bfd_reloc_status_type r = bfd_reloc_ok; - const char *name; + const char *name = NULL; bfd_vma off, ie_off; bfd_boolean unresolved_reloc, is_ie = FALSE; bfd_vma pc = sec_addr (input_section) + rel->r_offset; @@ -1689,6 +1932,19 @@ riscv_elf_relocate_section (bfd *output_bfd, sym = local_syms + r_symndx; sec = local_sections[r_symndx]; relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + + /* Relocate against local STT_GNU_IFUNC symbol. */ + if (!bfd_link_relocatable (info) + && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + { + h = riscv_elf_get_local_sym_hash (htab, input_bfd, rel, FALSE); + if (h == NULL) + abort (); + + /* Set STT_GNU_IFUNC symbol value. */ + h->root.u.def.value = sym->st_value; + h->root.u.def.section = sec; + } } else { @@ -1717,6 +1973,235 @@ riscv_elf_relocate_section (bfd *output_bfd, if (bfd_link_relocatable (info)) continue; + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle + it here if it is defined in a non-shared object. */ + if (h != NULL + && h->type == STT_GNU_IFUNC + && h->def_regular) + { + asection *plt, *base_got; + + if ((input_section->flags & SEC_ALLOC) == 0) + { + /* If this is a SHT_NOTE section without SHF_ALLOC, treat + STT_GNU_IFUNC symbol as STT_FUNC. */ + if (elf_section_type (input_section) == SHT_NOTE) + goto skip_ifunc; + + /* Dynamic relocs are not propagated for SEC_DEBUGGING + sections because such sections are not SEC_ALLOC and + thus ld.so will not process them. */ + if ((input_section->flags & SEC_DEBUGGING) != 0) + continue; + + abort (); + } + else if (h->plt.offset == (bfd_vma) -1 + /* The following relocation may not need the .plt entries + when all references to a STT_GNU_IFUNC symbols are done + via GOT or static function pointers. */ + && r_type != R_RISCV_32 + && r_type != R_RISCV_64 + && r_type != R_RISCV_HI20 + && r_type != R_RISCV_GOT_HI20 + && r_type != R_RISCV_LO12_I + && r_type != R_RISCV_LO12_S) + goto bad_ifunc_reloc; + + /* STT_GNU_IFUNC symbol must go through PLT. */ + plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; + relocation = plt->output_section->vma + + plt->output_offset + + h->plt.offset; + + switch (r_type) + { + case R_RISCV_32: + case R_RISCV_64: + if (rel->r_addend != 0) + { + if (h->root.root.string) + name = h->root.root.string; + else + name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); + + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: relocation %s against STT_GNU_IFUNC " + "symbol `%s' has non-zero addend: %" PRId64), + input_bfd, howto->name, name, (int64_t) rel->r_addend); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* Generate dynamic relocation only when there is a non-GOT + reference in a shared object or there is no PLT. */ + if ((bfd_link_pic (info) && h->non_got_ref) + || h->plt.offset == (bfd_vma) -1) + { + Elf_Internal_Rela outrel; + asection *sreloc; + + /* Need a dynamic relocation to get the real function + address. */ + outrel.r_offset = _bfd_elf_section_offset (output_bfd, + info, + input_section, + rel->r_offset); + if (outrel.r_offset == (bfd_vma) -1 + || outrel.r_offset == (bfd_vma) -2) + abort (); + + outrel.r_offset += input_section->output_section->vma + + input_section->output_offset; + + if (h->dynindx == -1 + || h->forced_local + || bfd_link_executable (info)) + { + info->callbacks->minfo + (_("Local IFUNC function `%s' in %pB\n"), + h->root.root.string, + h->root.u.def.section->owner); + + /* This symbol is resolved locally. */ + outrel.r_info = ELFNN_R_INFO (0, R_RISCV_IRELATIVE); + outrel.r_addend = h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset; + } + else + { + outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); + outrel.r_addend = 0; + } + + /* Dynamic relocations are stored in + 1. .rela.ifunc section in PIC object. + 2. .rela.got section in dynamic executable. + 3. .rela.iplt section in static executable. */ + if (bfd_link_pic (info)) + sreloc = htab->elf.irelifunc; + else if (htab->elf.splt != NULL) + sreloc = htab->elf.srelgot; + else + sreloc = htab->elf.irelplt; + + riscv_elf_append_rela (output_bfd, sreloc, &outrel); + + /* If this reloc is against an external symbol, we + do not want to fiddle with the addend. Otherwise, + we need to include the symbol value so that it + becomes an addend for the dynamic reloc. For an + internal symbol, we have updated addend. */ + continue; + } + goto do_relocation; + + case R_RISCV_GOT_HI20: + base_got = htab->elf.sgot; + off = h->got.offset; + + if (base_got == NULL) + abort (); + + if (off == (bfd_vma) -1) + { + bfd_vma plt_idx; + + /* We can't use h->got.offset here to save state, or + even just remember the offset, as finish_dynamic_symbol + would use that as offset into .got. */ + + if (htab->elf.splt != NULL) + { + plt_idx = (h->plt.offset - PLT_HEADER_SIZE) + / PLT_ENTRY_SIZE; + off = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE); + base_got = htab->elf.sgotplt; + } + else + { + plt_idx = h->plt.offset / PLT_ENTRY_SIZE; + off = plt_idx * GOT_ENTRY_SIZE; + base_got = htab->elf.igotplt; + } + + if (h->dynindx == -1 + || h->forced_local + || info->symbolic) + { + /* This references the local definition. We must + initialize this entry in the global offset table. + Since the offset must always be a multiple of 8, + we use the least significant bit to record + whether we have initialized it already. + + When doing a dynamic link, we create a .rela.got + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_NN (output_bfd, relocation, + base_got->contents + off); + /* Note that this is harmless for the case, + as -1 | 1 still is -1. */ + h->got.offset |= 1; + } + } + } + + relocation = base_got->output_section->vma + + base_got->output_offset + off; + + r_type = ELFNN_R_TYPE (rel->r_info); + howto = riscv_elf_rtype_to_howto (input_bfd, r_type); + if (howto == NULL) + r = bfd_reloc_notsupported; + else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc, + relocation, FALSE)) + r = bfd_reloc_overflow; + goto do_relocation; + + case R_RISCV_CALL: + case R_RISCV_CALL_PLT: + case R_RISCV_HI20: + case R_RISCV_LO12_I: + case R_RISCV_LO12_S: + goto do_relocation; + + case R_RISCV_PCREL_HI20: + r_type = ELFNN_R_TYPE (rel->r_info); + howto = riscv_elf_rtype_to_howto (input_bfd, r_type); + if (howto == NULL) + r = bfd_reloc_notsupported; + else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc, + relocation, FALSE)) + r = bfd_reloc_overflow; + goto do_relocation; + + default: + bad_ifunc_reloc: + if (h->root.root.string) + name = h->root.root.string; + else + /* The entry of local ifunc is fake in global hash table, + we should find the name by the original local symbol. */ + name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); + + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: relocation %s against STT_GNU_IFUNC " + "symbol `%s' isn't supported"), input_bfd, + howto->name, name); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + } + + skip_ifunc: if (h != NULL) name = h->root.root.string; else @@ -2013,6 +2498,7 @@ riscv_elf_relocate_section (bfd *output_bfd, || h->root.type == bfd_link_hash_undefined))) { Elf_Internal_Rela outrel; + asection *sreloc; bfd_boolean skip_static_relocation, skip_dynamic_relocation; /* When generating a shared object, these relocations @@ -2042,6 +2528,7 @@ riscv_elf_relocate_section (bfd *output_bfd, outrel.r_addend = relocation + rel->r_addend; } + sreloc = elf_section_data (input_section)->sreloc; riscv_elf_append_rela (output_bfd, sreloc, &outrel); if (skip_static_relocation) continue; @@ -2216,6 +2703,7 @@ riscv_elf_relocate_section (bfd *output_bfd, r = bfd_reloc_notsupported; } + do_relocation: if (r == bfd_reloc_ok) r = perform_relocation (howto, rel, relocation, input_section, input_bfd, contents); @@ -2299,23 +2787,58 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, { /* We've decided to create a PLT entry for this symbol. */ bfd_byte *loc; - bfd_vma i, header_address, plt_idx, got_address; + bfd_vma i, header_address, plt_idx, got_offset, got_address; uint32_t plt_entry[PLT_ENTRY_INSNS]; Elf_Internal_Rela rela; - - BFD_ASSERT (h->dynindx != -1); + asection *plt, *gotplt, *relplt; + + /* When building a static executable, use .iplt, .igot.plt and + .rela.iplt sections for STT_GNU_IFUNC symbols. */ + if (htab->elf.splt != NULL) + { + plt = htab->elf.splt; + gotplt = htab->elf.sgotplt; + relplt = htab->elf.srelplt; + } + else + { + plt = htab->elf.iplt; + gotplt = htab->elf.igotplt; + relplt = htab->elf.irelplt; + } + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ + if ((h->dynindx == -1 + && !((h->forced_local || bfd_link_executable (info)) + && h->def_regular + && h->type == STT_GNU_IFUNC)) + || plt == NULL + || gotplt == NULL + || relplt == NULL) + return FALSE; /* Calculate the address of the PLT header. */ - header_address = sec_addr (htab->elf.splt); + header_address = sec_addr (plt); - /* Calculate the index of the entry. */ - plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; + /* Calculate the index of the entry and the offset of .got.plt entry. + For static executables, we don't reserve anything. */ + if (plt == htab->elf.splt) + { + plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; + got_offset = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE); + } + else + { + plt_idx = h->plt.offset / PLT_ENTRY_SIZE; + got_offset = plt_idx * GOT_ENTRY_SIZE; + } /* Calculate the address of the .got.plt entry. */ - got_address = riscv_elf_got_plt_val (plt_idx, info); + got_address = sec_addr (gotplt) + got_offset; /* Find out where the .plt entry should go. */ - loc = htab->elf.splt->contents + h->plt.offset; + loc = plt->contents + h->plt.offset; /* Fill in the PLT entry itself. */ if (! riscv_make_plt_entry (output_bfd, got_address, @@ -2327,16 +2850,37 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, bfd_put_32 (output_bfd, plt_entry[i], loc + 4*i); /* Fill in the initial value of the .got.plt entry. */ - loc = htab->elf.sgotplt->contents - + (got_address - sec_addr (htab->elf.sgotplt)); - bfd_put_NN (output_bfd, sec_addr (htab->elf.splt), loc); + loc = gotplt->contents + (got_address - sec_addr (gotplt)); + bfd_put_NN (output_bfd, sec_addr (plt), loc); - /* Fill in the entry in the .rela.plt section. */ rela.r_offset = got_address; - rela.r_addend = 0; - rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_JUMP_SLOT); - loc = htab->elf.srelplt->contents + plt_idx * sizeof (ElfNN_External_Rela); + if (h->dynindx == -1 + || ((bfd_link_executable (info) + || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + && h->def_regular + && h->type == STT_GNU_IFUNC)) + { + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), + h->root.root.string, + h->root.u.def.section->owner); + + /* If an STT_GNU_IFUNC symbol is locally defined, generate + R_RISCV_IRELATIVE instead of R_RISCV_JUMP_SLOT. */ + asection *sec = h->root.u.def.section; + rela.r_info = ELFNN_R_INFO (0, R_RISCV_IRELATIVE); + rela.r_addend = h->root.u.def.value + + sec->output_section->vma + + sec->output_offset; + } + else + { + /* Fill in the entry in the .rela.plt section. */ + rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_JUMP_SLOT); + rela.r_addend = 0; + } + + loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela); bed->s->swap_reloca_out (output_bfd, &rela, loc); if (!h->def_regular) @@ -2369,13 +2913,73 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, rela.r_offset = sec_addr (sgot) + (h->got.offset &~ (bfd_vma) 1); + /* Handle the ifunc symbol in GOT entry. */ + if (h->def_regular + && h->type == STT_GNU_IFUNC) + { + if (h->plt.offset == (bfd_vma) -1) + { + /* STT_GNU_IFUNC is referenced without PLT. */ + if (htab->elf.splt == NULL) + { + /* use .rel[a].iplt section to store .got relocations + in static executable. */ + srela = htab->elf.irelplt; + } + if (SYMBOL_REFERENCES_LOCAL (info, h)) + { + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), + h->root.root.string, + h->root.u.def.section->owner); + + rela.r_info = ELFNN_R_INFO (0, R_RISCV_IRELATIVE); + rela.r_addend = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + /* Generate R_RISCV_NN. */ + BFD_ASSERT((h->got.offset & 1) == 0); + BFD_ASSERT (h->dynindx != -1); + rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_NN); + rela.r_addend = 0; + } + } + else if (bfd_link_pic (info)) + { + /* Generate R_RISCV_NN. */ + BFD_ASSERT((h->got.offset & 1) == 0); + BFD_ASSERT (h->dynindx != -1); + rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_NN); + rela.r_addend = 0; + } + else + { + asection *plt; + + if (!h->pointer_equality_needed) + abort (); + + /* For non-shared object, we can't use .got.plt, which + contains the real function address if we need pointer + equality. We load the GOT entry with the PLT entry. */ + plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; + bfd_put_NN (output_bfd, (plt->output_section->vma + + plt->output_offset + + h->plt.offset), + htab->elf.sgot->contents + + (h->got.offset & ~(bfd_vma) 1)); + return TRUE; + } + } /* If this is a local symbol reference, we just want to emit a RELATIVE reloc. This can happen if it is a -Bsymbolic link, or a pie link, or the symbol was forced to be local because of a version file. The entry in the global offset table will already have been initialized in the relocate_section function. */ - if (bfd_link_pic (info) - && SYMBOL_REFERENCES_LOCAL (info, h)) + else if (bfd_link_pic (info) + && SYMBOL_REFERENCES_LOCAL (info, h)) { BFD_ASSERT((h->got.offset & 1) != 0); asection *sec = h->root.u.def.section; @@ -2423,6 +3027,18 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, return TRUE; } +/* Finish up local dynamic symbol handling. We set the contents of + various dynamic sections here. */ + +static bfd_boolean +riscv_elf_finish_local_dynamic_symbol (void **slot, void *inf) +{ + struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot; + struct bfd_link_info *info = (struct bfd_link_info *) inf; + + return riscv_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL); +} + /* Finish up the dynamic sections. */ static bfd_boolean @@ -2549,6 +3165,11 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd, elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE; } + /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */ + htab_traverse (htab->loc_hash_table, + riscv_elf_finish_local_dynamic_symbol, + info); + return TRUE; } @@ -4052,6 +4673,12 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, reserve_size = (isym->st_size - rel->r_addend) > isym->st_size ? 0 : isym->st_size - rel->r_addend; + /* Relocate against local STT_GNU_IFUNC symbol. we have created + a fake global symbol entry for this, so deal with the local ifunc + as a global. */ + if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) + continue; + if (isym->st_shndx == SHN_UNDEF) sym_sec = sec, symval = rel->r_offset; else @@ -4082,6 +4709,10 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Disable the relaxation for ifunc. */ + if (h != NULL && h->type == STT_GNU_IFUNC) + continue; + if (h->root.type == bfd_link_hash_undefweak && (relax_func == _bfd_riscv_relax_lui || relax_func == _bfd_riscv_relax_pc)) diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index e5adea5..003df59 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -854,6 +854,21 @@ static reloc_howto_type howto_table[] = 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* Relocation against a local ifunc symbol in a shared object. */ + HOWTO (R_RISCV_IRELATIVE, /* type */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_IRELATIVE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ diff --git a/include/ChangeLog b/include/ChangeLog index 8fdf30f..5c1145a 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2020-10-16 Nelson Chu <nelson.chu@sifive.com> + + * elf/riscv.h: Add R_RISCV_IRELATIVE to 58. + 2020-10-09 H.J. Lu <hongjiu.lu@intel.com> PR gas/26703 diff --git a/include/elf/riscv.h b/include/elf/riscv.h index 5062a49..98c7ac6 100644 --- a/include/elf/riscv.h +++ b/include/elf/riscv.h @@ -88,6 +88,7 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type) RELOC_NUMBER (R_RISCV_SET16, 55) RELOC_NUMBER (R_RISCV_SET32, 56) RELOC_NUMBER (R_RISCV_32_PCREL, 57) + RELOC_NUMBER (R_RISCV_IRELATIVE, 58) END_RELOC_NUMBERS (R_RISCV_max) /* Processor specific flags for the ELF header e_flags field. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 205f6ac..3a9d381 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,60 @@ +2020-10-16 Nelson Chu <nelson.chu@sifive.com> + + * emulparams/elf32lriscv-defs.sh: Add IREL_IN_PLT. + * testsuite/ld-ifunc/ifunc.exp: Enable ifunc tests for RISC-V. + * testsuite/ld-riscv-elf/ld-riscv-elf.exp (run_dump_test_ifunc): + New dump test for ifunc. There are two arguments, 'target` and + `output`. The `target` is rv32 or rv64, and the `output` is used + to choose which output you want to test (exe, pie or .so). + * testsuite/ld-riscv-elf/ifunc-reloc-call-01.s: New testcase. + * testsuite/ld-riscv-elf/ifunc-reloc-call-01.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-01-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-01-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-01-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-02.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-02.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-02-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-02-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-call-02-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-data.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-data.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-data-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-data-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-data-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-got.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-got.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-got-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-got-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-got-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-pcrel.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-pcrel.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-pcrel-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-nonplt.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-nonplt.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-nonplt-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-nonplt-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-nonplt-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-01.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-01.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-01-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-01-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-01-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-02.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-02.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-02-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-02-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-02-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-resolver.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-caller.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-exe.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-pic.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-pie.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-caller-pcrel.s: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pic.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pie.d: Likewise. + 2020-10-09 H.J. Lu <hongjiu.lu@intel.com> PR gas/26703 diff --git a/ld/emulparams/elf32lriscv-defs.sh b/ld/emulparams/elf32lriscv-defs.sh index bc46491..b823ced 100644 --- a/ld/emulparams/elf32lriscv-defs.sh +++ b/ld/emulparams/elf32lriscv-defs.sh @@ -26,6 +26,7 @@ case "$target" in ;; esac +IREL_IN_PLT= TEXT_START_ADDR=0x10000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp index 63ab18d..9ed4bd7 100644 --- a/ld/testsuite/ld-ifunc/ifunc.exp +++ b/ld/testsuite/ld-ifunc/ifunc.exp @@ -39,7 +39,6 @@ if { ![is_elf_format] || ![supports_gnu_osabi] || [istarget nds32*-*-*] || [istarget nios2-*-*] || [istarget or1k-*-*] - || [istarget riscv*-*-*] || [istarget score*-*-*] || [istarget sh*-*-*] || [istarget tic6x-*-*] @@ -736,7 +735,8 @@ run_ld_link_exec_tests [list \ if { [isnative] && !([istarget "powerpc-*-*"] || [istarget "aarch64*-*-*"] - || [istarget "sparc*-*-*"]) } { + || [istarget "sparc*-*-*"] + || [istarget "riscv*-*-*"]) } { run_ld_link_exec_tests [list \ [list \ "Run pr23169a" \ diff --git a/ld/testsuite/ld-riscv-elf/ifunc-nonplt-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-nonplt-exe.rd new file mode 100644 index 0000000..0de47a4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-nonplt-exe.rd @@ -0,0 +1,4 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-nonplt-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-nonplt-pic.rd new file mode 100644 index 0000000..e2e7ad9 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-nonplt-pic.rd @@ -0,0 +1,7 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 +#... +Relocation section '.rela.ifunc' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-nonplt-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-nonplt-pie.rd new file mode 100644 index 0000000..f9fbd87 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-nonplt-pie.rd @@ -0,0 +1,7 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* +#... +Relocation section '.rela.ifunc' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-nonplt.d b/ld/testsuite/ld-riscv-elf/ifunc-nonplt.d new file mode 100644 index 0000000..e3517d3 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-nonplt.d @@ -0,0 +1,11 @@ +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(_GLOBAL_OFFSET_TABLE_.*|.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(__DATA_BEGIN__|.*)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-nonplt.s b/ld/testsuite/ld-riscv-elf/ifunc-nonplt.s new file mode 100644 index 0000000..ce6ca69 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-nonplt.s @@ -0,0 +1,39 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %got_pcrel_hi (foo) +.ifdef __64_bit__ + ld x1, %pcrel_lo (.L1) (x1) +.else + lw x1, %pcrel_lo (.L1) (x1) +.endif + +.L2: + auipc x2, %pcrel_hi (foo_addr) +.ifdef __64_bit__ + ld x2, %pcrel_lo (.L2) (x2) +.else + lw x2, %pcrel_lo (.L2) (x2) +.endif + ret + .size bar, .-bar + + .data +foo_addr: +.ifdef __64_bit__ + .quad foo +.else + .long foo +.endif diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-01-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-01-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-01-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-01-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-01-pic.rd new file mode 100644 index 0000000..6f5218b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-01-pic.rd @@ -0,0 +1,7 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-01-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-01-pie.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-01-pie.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-01.d b/ld/testsuite/ld-riscv-elf/ifunc-plt-01.d new file mode 100644 index 0000000..bed9fe6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-01.d @@ -0,0 +1,19 @@ +#... +Disassembly of section .plt: +#... +0+[0-9a-f]+ <(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)>: +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(_GLOBAL_OFFSET_TABLE_.*|__DATA_BEGIN__.*|.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+addi[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-01.s b/ld/testsuite/ld-riscv-elf/ifunc-plt-01.s new file mode 100644 index 0000000..65c65cd --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-01.s @@ -0,0 +1,31 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %got_pcrel_hi (foo) +.ifdef __64_bit__ + ld x1, %pcrel_lo (.L1) (x1) +.else + lw x1, %pcrel_lo (.L1) (x1) +.endif + +.L2: + auipc x2, %pcrel_hi (foo) + addi x2, x2, %pcrel_lo (.L2) + + call foo + call foo@plt + + ret + .size bar, .-bar diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-02-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-02-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-02-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-02-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-02-pic.rd new file mode 100644 index 0000000..3299aa4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-02-pic.rd @@ -0,0 +1,11 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 +#... +Relocation section '.rela.ifunc' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-02-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-02-pie.rd new file mode 100644 index 0000000..28a3c99 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-02-pie.rd @@ -0,0 +1,7 @@ +Relocation section '.rela.ifunc' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-02.d b/ld/testsuite/ld-riscv-elf/ifunc-plt-02.d new file mode 100644 index 0000000..b8638b9 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-02.d @@ -0,0 +1,21 @@ +#... +Disassembly of section .plt: +#... +0+[0-9a-f]+ <(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)>: +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(_GLOBAL_OFFSET_TABLE_.*|.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(__DATA_BEGIN__.*|.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+addi[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-02.s b/ld/testsuite/ld-riscv-elf/ifunc-plt-02.s new file mode 100644 index 0000000..c3022be --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-02.s @@ -0,0 +1,46 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %got_pcrel_hi (foo) +.ifdef __64_bit__ + ld x1, %pcrel_lo (.L1) (x1) +.else + lw x1, %pcrel_lo (.L1) (x1) +.endif + +.L2: + auipc x2, %pcrel_hi (foo_addr) +.ifdef __64_bit__ + ld x2, %pcrel_lo (.L2) (x2) +.else + lw x2, %pcrel_lo (.L2) (x2) +.endif + +.L3: + auipc x3, %pcrel_hi (foo) + addi x3, x3, %pcrel_lo (.L3) + + call foo + call foo@plt + ret + .size bar, .-bar + + .data +foo_addr: +.ifdef __64_bit__ + .quad foo +.else + .long foo +.endif diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pic.rd new file mode 100644 index 0000000..7bfaa2d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pic.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pie.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pie.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.d b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.d new file mode 100644 index 0000000..d4457c9 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.d @@ -0,0 +1,13 @@ +#... +Disassembly of section .plt: +#... +0+[0-9a-f]+ <(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)>: +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.s b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.s new file mode 100644 index 0000000..89e6326 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.s @@ -0,0 +1,17 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: + call foo + ret + .size bar, .-bar diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pic.rd new file mode 100644 index 0000000..7bfaa2d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pic.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pie.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pie.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.d b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.d new file mode 100644 index 0000000..40c0309 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.d @@ -0,0 +1,15 @@ +#... +Disassembly of section .plt: +#... +0+[0-9a-f]+ <(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)>: +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.s b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.s new file mode 100644 index 0000000..e493c47 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.s @@ -0,0 +1,18 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: + call foo@plt + call foo + ret + .size bar, .-bar diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pic.rd new file mode 100644 index 0000000..9be346b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pic.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.ifunc' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pie.rd new file mode 100644 index 0000000..e14b02b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pie.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.ifunc' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-data.d b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data.d new file mode 100644 index 0000000..1956cc3 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data.d @@ -0,0 +1,9 @@ +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(__DATA_BEGIN__.*|.*)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-data.s b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data.s new file mode 100644 index 0000000..b49bda1 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-data.s @@ -0,0 +1,31 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %pcrel_hi (foo_addr) +.ifdef __64_bit__ + ld x1, %pcrel_lo (.L1) (x1) +.else + lw x1, %pcrel_lo (.L1) (x1) +.endif + ret + .size bar, .-bar + + .data +foo_addr: +.ifdef __64_bit__ + .quad foo +.else + .long foo +.endif diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pic.rd new file mode 100644 index 0000000..41cbc07 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pic.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pie.rd new file mode 100644 index 0000000..cef1a77 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pie.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-got.d b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got.d new file mode 100644 index 0000000..3277e8f --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got.d @@ -0,0 +1,9 @@ +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(_GLOBAL_OFFSET_TABLE_.*|.*)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-got.s b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got.s new file mode 100644 index 0000000..eca16d5 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-got.s @@ -0,0 +1,23 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %got_pcrel_hi (foo) +.ifdef __64_bit__ + ld x1, %pcrel_lo (.L1) (x1) +.else + lw x1, %pcrel_lo (.L1) (x1) +.endif + ret + .size bar, .-bar diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-exe.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-exe.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pic.rd new file mode 100644 index 0000000..7bfaa2d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pic.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pie.rd new file mode 100644 index 0000000..97461e4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pie.rd @@ -0,0 +1,3 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.d b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.d new file mode 100644 index 0000000..bc947e3 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.d @@ -0,0 +1,15 @@ +#... +Disassembly of section .plt: +#... +0+[0-9a-f]+ <(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)>: +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+addi[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.s b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.s new file mode 100644 index 0000000..7ea454c --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.s @@ -0,0 +1,26 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %pcrel_hi (foo) + addi x1, x1, %pcrel_lo (.L1) +.L2: + auipc x2, %pcrel_hi (foo) +.ifdef __64_bit__ + ld x2, %pcrel_lo (.L2) (x2) +.else + lw x2, %pcrel_lo (.L2) (x2) +.endif + ret + .size bar, .-bar diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s new file mode 100644 index 0000000..23c7254 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s @@ -0,0 +1,23 @@ + .text + + # Call the IFUNC `foo` which is defined in the other modules. + .globl foo + .type foo, %function + + .globl main + .type main, @function +main: +.L1: + auipc x1, %got_pcrel_hi (foo) + addi x1, x1, %pcrel_lo (.L1) + +.L2: + auipc x2, %pcrel_hi (foo_addr) + addi x2, x2, %pcrel_lo (.L2) + + ret + .size main, .-main + + .data +foo_addr: + .long foo diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-pcrel.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-pcrel.s new file mode 100644 index 0000000..2d29bcd --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-pcrel.s @@ -0,0 +1,14 @@ + .text + + # Call the IFUNC `foo` which is defined in the other modules. + .globl foo + .type foo, %function + + .globl main + .type main, @function +main: +.L1: + auipc x1, %pcrel_hi (foo) + addi x1, x1, %pcrel_lo (.L1) + ret + .size main, .-main diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s new file mode 100644 index 0000000..8aa6403 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s @@ -0,0 +1,26 @@ + .text + + # Call the IFUNC `foo` which is defined in the other modules. + .globl foo + .type foo, %function + + .globl main + .type main, @function +main: +.L1: + auipc x1, %got_pcrel_hi (foo) + addi x1, x1, %pcrel_lo (.L1) + +.L2: + auipc x2, %pcrel_hi (foo_addr) + addi x2, x2, %pcrel_lo (.L2) + + call foo + call foo@plt + + ret + .size main, .-main + + .data +foo_addr: + .long foo diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-exe.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-exe.d new file mode 100644 index 0000000..540a21b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-exe.d @@ -0,0 +1,14 @@ +#name: Link shared ifunc resolver with non-PLT caller (exe) +#source: ifunc-seperate-caller-nonplt.s +#as: +#ld: -z nocombreloc tmpdir/ifunc-seperate-resolver.so +#warning: .* +#readelf: -rW + +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+[0-9a-f]+[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pic.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pic.d new file mode 100644 index 0000000..3ed1812 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pic.d @@ -0,0 +1,13 @@ +#name: Link shared ifunc resolver with non-PLT caller (pic) +#source: ifunc-seperate-caller-nonplt.s +#as: +#ld: -z nocombreloc -shared tmpdir/ifunc-seperate-resolver.so +#readelf: -rW + +Relocation section '.rela.data' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pie.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pie.d new file mode 100644 index 0000000..c9c9eab --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pie.d @@ -0,0 +1,14 @@ +#name: Link shared ifunc resolver with non-PLT caller (pie) +#source: ifunc-seperate-caller-nonplt.s +#as: +#ld: -z nocombreloc -pie tmpdir/ifunc-seperate-resolver.so +#warning: .* +#readelf: -rW + +Relocation section '.rela.data' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pic.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pic.d new file mode 100644 index 0000000..1c11a2d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pic.d @@ -0,0 +1,5 @@ +#name: Link shared IFUNC resolver with PCREL caller (pic) +#source: ifunc-seperate-caller-pcrel.s +#as: +#ld: -z nocombreloc -shared tmpdir/ifunc-seperate-resolver.so +#error: .*unresolvable R_RISCV_PCREL_HI20 relocation.* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pie.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pie.d new file mode 100644 index 0000000..0d0e3cc --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pie.d @@ -0,0 +1,5 @@ +#name: Link shared IFUNC resolver with PCREL caller (pie) +#source: ifunc-seperate-caller-pcrel.s +#as: +#ld: -z nocombreloc -pie tmpdir/ifunc-seperate-resolver.so +#error: .*unresolvable R_RISCV_PCREL_HI20 relocation.* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-exe.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-exe.d new file mode 100644 index 0000000..a538564 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-exe.d @@ -0,0 +1,14 @@ +#name: Link shared ifunc resolver with PLT caller (exe) +#source: ifunc-seperate-caller-plt.s +#as: +#ld: -z nocombreloc tmpdir/ifunc-seperate-resolver.so +#warning: .* +#readelf: -rW + +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+[0-9a-f]+[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pic.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pic.d new file mode 100644 index 0000000..9efa244 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pic.d @@ -0,0 +1,17 @@ +#name: Link shared ifunc resolver with PLT caller (pic) +#source: ifunc-seperate-caller-plt.s +#as: +#ld: -z nocombreloc -shared tmpdir/ifunc-seperate-resolver.so +#readelf: -rW + +Relocation section '.rela.data' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+[0-9a-f]+[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pie.d b/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pie.d new file mode 100644 index 0000000..8349e61 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pie.d @@ -0,0 +1,18 @@ +#name: Link shared ifunc resolver with PLT caller (pie) +#source: ifunc-seperate-caller-plt.s +#as: +#ld: -z nocombreloc -pie tmpdir/ifunc-seperate-resolver.so +#warning: .* +#readelf: -rW + +Relocation section '.rela.data' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+[0-9a-f]+[ ]+foo \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+[0-9a-f]+[ ]+foo \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-seperate-resolver.s b/ld/testsuite/ld-riscv-elf/ifunc-seperate-resolver.s new file mode 100644 index 0000000..a222847 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-seperate-resolver.s @@ -0,0 +1,11 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + # The ifunc `foo` is called by the ifunc-caller. + .globl foo + .type foo, %gnu_indirect_function + .set foo, foo_resolver diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index 2c008d4..b82e092 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -19,6 +19,47 @@ # MA 02110-1301, USA. # +# target: rv32 or rv64. +# output: Which output you want? (exe, pie, .so) +proc run_dump_test_ifunc { name target output} { + set asflags "" + set ldflags "-z nocombreloc" + + switch -- $output { + exe { + set ext "exe" + } + 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 -melf32lriscv" + } + rv64 { + set asflags "$asflags -march=rv64i -mabi=lp64 -defsym __64_bit__=1" + set ldflags "$ldflags -melf64lriscv" + } + } + + run_ld_link_tests [list \ + [list "$name ($target-$output)" \ + "$ldflags" "" \ + "$asflags" \ + [list "$name.s"] \ + [concat [list "readelf -rW $name-$output.rd"] \ + [list "objdump -dw $name.d"]] \ + "$name-$target.$ext"]] +} + if [istarget "riscv*-*-*"] { run_dump_test "call-relax" run_dump_test "c-lui" @@ -88,4 +129,74 @@ if [istarget "riscv*-*-*"] { {} "lib-nopic-01a.so" } } run_dump_test "lib-nopic-01b" + + # IFUNC testcases. + # Check IFUNC by single type relocs. + run_dump_test_ifunc "ifunc-reloc-call-01" rv32 exe + run_dump_test_ifunc "ifunc-reloc-call-01" rv32 pie + run_dump_test_ifunc "ifunc-reloc-call-01" rv32 pic + run_dump_test_ifunc "ifunc-reloc-call-02" rv32 exe + run_dump_test_ifunc "ifunc-reloc-call-02" rv32 pie + run_dump_test_ifunc "ifunc-reloc-call-02" rv32 pic + run_dump_test_ifunc "ifunc-reloc-pcrel" rv32 exe + run_dump_test_ifunc "ifunc-reloc-pcrel" rv32 pie + run_dump_test_ifunc "ifunc-reloc-pcrel" rv32 pic + run_dump_test_ifunc "ifunc-reloc-data" rv32 exe + run_dump_test_ifunc "ifunc-reloc-data" rv32 pie + run_dump_test_ifunc "ifunc-reloc-data" rv32 pic + run_dump_test_ifunc "ifunc-reloc-got" rv32 exe + run_dump_test_ifunc "ifunc-reloc-got" rv32 pie + run_dump_test_ifunc "ifunc-reloc-got" rv32 pic + run_dump_test_ifunc "ifunc-reloc-pcrel" rv64 exe + run_dump_test_ifunc "ifunc-reloc-pcrel" rv64 pie + run_dump_test_ifunc "ifunc-reloc-pcrel" rv64 pic + run_dump_test_ifunc "ifunc-reloc-data" rv64 exe + run_dump_test_ifunc "ifunc-reloc-data" rv64 pie + run_dump_test_ifunc "ifunc-reloc-data" rv64 pic + run_dump_test_ifunc "ifunc-reloc-got" rv64 exe + run_dump_test_ifunc "ifunc-reloc-got" rv64 pie + run_dump_test_ifunc "ifunc-reloc-got" rv64 pic + # Check the IFUNC PLT and non-PLT relocs. + run_dump_test_ifunc "ifunc-nonplt" rv32 exe + run_dump_test_ifunc "ifunc-nonplt" rv32 pie + run_dump_test_ifunc "ifunc-nonplt" rv32 pic + run_dump_test_ifunc "ifunc-plt-01" rv32 exe + run_dump_test_ifunc "ifunc-plt-01" rv32 pie + run_dump_test_ifunc "ifunc-plt-01" rv32 pic + run_dump_test_ifunc "ifunc-plt-02" rv32 exe + run_dump_test_ifunc "ifunc-plt-02" rv32 pie + run_dump_test_ifunc "ifunc-plt-02" rv32 pic + run_dump_test_ifunc "ifunc-nonplt" rv64 exe + run_dump_test_ifunc "ifunc-nonplt" rv64 pie + run_dump_test_ifunc "ifunc-nonplt" rv64 pic + run_dump_test_ifunc "ifunc-plt-01" rv64 exe + run_dump_test_ifunc "ifunc-plt-01" rv64 pie + run_dump_test_ifunc "ifunc-plt-01" rv64 pic + run_dump_test_ifunc "ifunc-plt-02" rv64 exe + run_dump_test_ifunc "ifunc-plt-02" rv64 pie + run_dump_test_ifunc "ifunc-plt-02" rv64 pic + + # Setup shared libraries. + run_ld_link_tests { + { "Build shared library for IFUNC non-PLT caller" + "-shared" "" "" {ifunc-seperate-caller-nonplt.s} + {} "ifunc-seperate-caller.so" } + { "Build shared library for IFUNC PLT caller" + "-shared" "" "" {ifunc-seperate-caller-plt.s} + {} "ifunc-seperate-caller.so" } + { "Build shared library for IFUNC resolver" + "-shared" "" "" {ifunc-seperate-resolver.s} + {} "ifunc-seperate-resolver.so" } + } + # The IFUNC resolver and caller are in the seperate modules. + # If IFUNC resolver and caller are linked to the same module, + # then the result are the same as the run_dump_test_ifunc. + run_dump_test "ifunc-seperate-nonplt-exe" + run_dump_test "ifunc-seperate-nonplt-pie" + run_dump_test "ifunc-seperate-nonplt-pic" + run_dump_test "ifunc-seperate-plt-exe" + run_dump_test "ifunc-seperate-plt-pie" + run_dump_test "ifunc-seperate-plt-pic" + run_dump_test "ifunc-seperate-pcrel-pie" + run_dump_test "ifunc-seperate-pcrel-pic" } |