[PATCH v3 1/2] RISC-V: Support GNU indirect functions.
Fangrui Song
i@maskray.me
Wed Jan 6 06:46:32 GMT 2021
More information about the Binutils mailing list
Wed Jan 6 06:46:32 GMT 2021
- Previous message (by thread): testsuite layout conventions
- Next message (by thread): [PATCH] ld: xfail riscv64be-*-* for ld-scripts/empty-address-2 tests.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Tue, Oct 6, 2020 at 8:48 PM Nelson Chu <nelson.chu@sifive.com> wrote: > > Generally, glibc dynamic linker should have two ways to deal with ifunc > - one is to handle the IRELATIVE relocations for the non-preemtive ifunc > symbols, the other is to handle the R_RISCV_32/64 and R_RISCV_JUMP_SLOT > relocations with the STT_IFUNC preemtive symbols. No matter which method > is used, both of them should get the resolved ifunc symbols at runtime. > Therefore, linker needs to generate the correct dynamic relocations for > ifunc to make sure the the dynamic linker works well. For now, there are > thirteen relocations are supported for ifunc in GNU ld, > > * R_RISCV_CALL and R_RISCV_CALL_PLT: > The RISC-V compiler won't generate R_RISCV_JAL directly to jump to an > ifunc. Besides, we disable the relaxations for the relocation referenced > to ifunc, so just handling the R_RISCV_CALL and R_RISCV_CALL_PLT should be > enough. Linker should generate a .plt entry and a .got.plt entry for it, > and also needs to insert a dynamic IRELATIVE in the .got.plt enrty, or > insert a R_RISCV_JUMP_SLOT when generating shared library. > > * R_RISCV_PCREL_HI20 and R_RISCV_PCREL_LO12_I/S: > LA/LLA pattern with local fPIC ifunc symbol, or any non-PIC ifunc symbol. > The PC-relative relocation. The current linker will deal with them in > the same way as R_RISCV_CALL_PLT. > > * R_RISCV_GOT_HI20 and R_RISCV_PCREL_LO12_I/S: > LA pattern with global PIC ifunc symbol. Linker should insert a dynamic > IRELATIVE in the .got entry, or insert a R_RISCV_32/64 when generating > shared library. > > * R_RISCV_32 and R_RISCV_64: > Store the ifunc symbol into the data section. Linker should insert a > dynamic IRELATIVE in the data section, or insert a R_RISCV_32/64 when > generating shared library. > > * R_RISCV_HI20 and R_RISCV_LO12_I/S: > The LUI + ADDI/LW/SW patterns. The absolute access relocation. The > medlow model without the -fPIC compiler option should generate them. > The ld ifunc testsuites "Build pr23169a" and "Build pr23169d" need the > relocations, they are in the ld/testsuite/ld-ifunc/, and need compiler > support. > > However, we also made some optimizations with reference to x86, > > * If GOT and PLT relocations refer to the same ifunc symbol when generating > pie, then they can actually share a .got entry without creating two entries > to store the same value and relocation. > > * If GOT, PLT and DATA relocations refer to the same ifunc symbol when > generating position dependency executable, then linker will fill the address > of .plt entry into the corresponding .got entry and data section, without > insert any dynamic relocations for the GOT and DATA relocations. > > For the ifunc testcases, there are three types of them, > > 1. ifunc-reloc-*: Only check the single type of relocation refers to > ifunc symbol. > * ifunc-reloc-call: R_RISCV_CALL and R_RISCV_CALL_PLT. > * ifunc-reloc-data: R_RISCV_32 and R_RISCV_64. > * ifunc-reloc-got: R_RISCV_GOT_HI20 and R_RISCV_PCREL_LO_I/S. > * ifunc-reloc-pcrel: R_RISCV_PCREL_HI20 and R_RISCV_PCREL_LO_I/S. > > 2. ifunc-[nonplt|plt]-*: If we don't have PLT relocs, then don't need to > create the PLT and it's .plt entries. > * ifunc-nonplt: Combine R_RISCV_GOT_HI20 and R_RISCV_32/64. > * ifunc-plt: Combine all ifunc relocations. > > 3. ifunc-seperate-*: If we link the ifunc caller and resolver into the > same module (link the objects), then the results are the same as the > ifunc-reloc-* and ifunc-[noplt|plt]-* testcases. Consider the cases that > the ifunc callers and resolver are in the different modules, that is, we > compile the ifunc resolver to the shared library first, and then link it > with the ifunc callers. The output of ifunc callers should be the same as > the normal STT_FUNC cases, and the shared ifunc resolver should define the > symbols as STT_IFUNC. > > The R_RISCV_PCREL_HI20 reloc is special. It should be linked and resolved > locally, so if the ifunc resolver is defined in other modules (other shared > libraries), then the R_RISCV_PCREL_HI20 is unresolvable, and linker should > issue an unresolvable reloc error. > > bfd/ > * 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. > > include/ > * elf/riscv.h: Add R_RISCV_IRELATIVE to 58. > > ld/ > * 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. > --- > bfd/configure | 4 +- > bfd/configure.ac | 4 +- > bfd/elfnn-riscv.c | 725 +++++++++++++++++++-- > bfd/elfxx-riscv.c | 15 + > include/elf/riscv.h | 1 + > ld/emulparams/elf32lriscv-defs.sh | 1 + > ld/testsuite/ld-ifunc/ifunc.exp | 4 +- > ld/testsuite/ld-riscv-elf/ifunc-nonplt-exe.rd | 4 + > ld/testsuite/ld-riscv-elf/ifunc-nonplt-pic.rd | 7 + > ld/testsuite/ld-riscv-elf/ifunc-nonplt-pie.rd | 7 + > ld/testsuite/ld-riscv-elf/ifunc-nonplt.d | 11 + > ld/testsuite/ld-riscv-elf/ifunc-nonplt.s | 39 ++ > ld/testsuite/ld-riscv-elf/ifunc-plt-01-exe.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-plt-01-pic.rd | 7 + > ld/testsuite/ld-riscv-elf/ifunc-plt-01-pie.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-plt-01.d | 19 + > ld/testsuite/ld-riscv-elf/ifunc-plt-01.s | 31 + > ld/testsuite/ld-riscv-elf/ifunc-plt-02-exe.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-plt-02-pic.rd | 11 + > ld/testsuite/ld-riscv-elf/ifunc-plt-02-pie.rd | 7 + > ld/testsuite/ld-riscv-elf/ifunc-plt-02.d | 21 + > ld/testsuite/ld-riscv-elf/ifunc-plt-02.s | 46 ++ > .../ld-riscv-elf/ifunc-reloc-call-01-exe.rd | 3 + > .../ld-riscv-elf/ifunc-reloc-call-01-pic.rd | 3 + > .../ld-riscv-elf/ifunc-reloc-call-01-pie.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.d | 13 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.s | 17 + > .../ld-riscv-elf/ifunc-reloc-call-02-exe.rd | 3 + > .../ld-riscv-elf/ifunc-reloc-call-02-pic.rd | 3 + > .../ld-riscv-elf/ifunc-reloc-call-02-pie.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.d | 15 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.s | 18 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-data-exe.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pic.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pie.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-data.d | 9 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-data.s | 31 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-got-exe.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pic.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pie.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-got.d | 9 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-got.s | 23 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-exe.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pic.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pie.rd | 3 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.d | 15 + > ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.s | 26 + > .../ld-riscv-elf/ifunc-seperate-caller-nonplt.s | 23 + > .../ld-riscv-elf/ifunc-seperate-caller-pcrel.s | 14 + > .../ld-riscv-elf/ifunc-seperate-caller-plt.s | 26 + > .../ld-riscv-elf/ifunc-seperate-nonplt-exe.d | 14 + > .../ld-riscv-elf/ifunc-seperate-nonplt-pic.d | 13 + > .../ld-riscv-elf/ifunc-seperate-nonplt-pie.d | 14 + > .../ld-riscv-elf/ifunc-seperate-pcrel-pic.d | 5 + > .../ld-riscv-elf/ifunc-seperate-pcrel-pie.d | 5 + > ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-exe.d | 14 + > ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pic.d | 17 + > ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pie.d | 18 + > .../ld-riscv-elf/ifunc-seperate-resolver.s | 11 + > ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 111 ++++ > 60 files changed, 1426 insertions(+), 53 deletions(-) > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-nonplt-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-nonplt-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-nonplt-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-nonplt.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-nonplt.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-01-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-01-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-01-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-01.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-01.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-02-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-02-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-02-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-02.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-plt-02.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-01.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-call-02.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-data-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-data-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-data.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-data.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-got-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-got-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-got.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-got.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-exe.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pic.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel-pie.rd > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-reloc-pcrel.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-nonplt.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-pcrel.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-caller-plt.s > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-exe.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pic.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-nonplt-pie.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pic.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-pcrel-pie.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-exe.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pic.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-plt-pie.d > create mode 100644 ld/testsuite/ld-riscv-elf/ifunc-seperate-resolver.s > > 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. */ A local definition includes -Bsymbolic. Filed https://sourceware.org/bugzilla/show_bug.cgi?id=27153 (very minor issue). The symbol representation needs a preemptible bit to avoid issues in various backends. > + 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/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/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" > } > -- > 2.7.4 >
- Previous message (by thread): testsuite layout conventions
- Next message (by thread): [PATCH] ld: xfail riscv64be-*-* for ld-scripts/empty-address-2 tests.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list