From 5ef237932919a19fe85f70fc37f7d3a0660b7665 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Tue, 25 Sep 2018 13:13:23 -0700 Subject: [PATCH] RISC-V: Give error for RVE PLTs. bfd/ * elfnn-riscv.c (riscv_make_plt_header): New arg output_bfd. Change return type to bfd_boolean. If EF_RISCV_RVE call _bfd_error_handler and return FALSE. Return TRUE at end. (riscv_make_plt_entry): Likewise. (riscv_elf_finish_dynamic_symbol): Update call to riscv_make_plt_entry. (riscv_elf_finish_dynamic_sections): Update call to riscv_make_plt_header. --- bfd/ChangeLog | 10 ++++++++++ bfd/elfnn-riscv.c | 44 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e8e31952caf..62cf91decf9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2018-09-25 Jim Wilson + + * elfnn-riscv.c (riscv_make_plt_header): New arg output_bfd. Change + return type to bfd_boolean. If EF_RISCV_RVE call _bfd_error_handler + and return FALSE. Return TRUE at end. + (riscv_make_plt_entry): Likewise. + (riscv_elf_finish_dynamic_symbol): Update call to riscv_make_plt_entry. + (riscv_elf_finish_dynamic_sections): Update call to + riscv_make_plt_header. + 2018-09-24 Jim Wilson * elfnn-riscv.c (_bfd_riscv_relax_pc) : New local diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index f3e2cc7c377..c99bcff5f1b 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -169,12 +169,21 @@ riscv_elf_got_plt_val (bfd_vma plt_index, struct bfd_link_info *info) /* Generate a PLT header. */ -static void -riscv_make_plt_header (bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry) +static bfd_boolean +riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr, + uint32_t *entry) { bfd_vma gotplt_offset_high = RISCV_PCREL_HIGH_PART (gotplt_addr, addr); bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr, addr); + /* RVE has no t3 register, so this won't work, and is not supported. */ + if (elf_elfheader (output_bfd)->e_flags & EF_RISCV_RVE) + { + _bfd_error_handler (_("%pB: warning: RVE PLT generation not supported"), + output_bfd); + return FALSE; + } + /* auipc t2, %hi(.got.plt) sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12 l[w|d] t3, %lo(.got.plt)(t2) # _dl_runtime_resolve @@ -192,13 +201,24 @@ riscv_make_plt_header (bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry) entry[5] = RISCV_ITYPE (SRLI, X_T1, X_T1, 4 - RISCV_ELF_LOG_WORD_BYTES); entry[6] = RISCV_ITYPE (LREG, X_T0, X_T0, RISCV_ELF_WORD_BYTES); entry[7] = RISCV_ITYPE (JALR, 0, X_T3, 0); + + return TRUE; } /* Generate a PLT entry. */ -static void -riscv_make_plt_entry (bfd_vma got, bfd_vma addr, uint32_t *entry) +static bfd_boolean +riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr, + uint32_t *entry) { + /* RVE has no t3 register, so this won't work, and is not supported. */ + if (elf_elfheader (output_bfd)->e_flags & EF_RISCV_RVE) + { + _bfd_error_handler (_("%pB: warning: RVE PLT generation not supported"), + output_bfd); + return FALSE; + } + /* auipc t3, %hi(.got.plt entry) l[w|d] t3, %lo(.got.plt entry)(t3) jalr t1, t3 @@ -208,6 +228,8 @@ riscv_make_plt_entry (bfd_vma got, bfd_vma addr, uint32_t *entry) entry[1] = RISCV_ITYPE (LREG, X_T3, X_T3, RISCV_PCREL_LOW_PART (got, addr)); entry[2] = RISCV_ITYPE (JALR, X_T1, X_T3, 0); entry[3] = RISCV_NOP; + + return TRUE; } /* Create an entry in an RISC-V ELF linker hash table. */ @@ -2353,8 +2375,11 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, loc = htab->elf.splt->contents + h->plt.offset; /* Fill in the PLT entry itself. */ - riscv_make_plt_entry (got_address, header_address + h->plt.offset, - plt_entry); + if (! riscv_make_plt_entry (output_bfd, got_address, + header_address + h->plt.offset, + plt_entry)) + return FALSE; + for (i = 0; i < PLT_ENTRY_INSNS; i++) bfd_put_32 (output_bfd, plt_entry[i], loc + 4*i); @@ -2529,8 +2554,11 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd, { int i; uint32_t plt_header[PLT_HEADER_INSNS]; - riscv_make_plt_header (sec_addr (htab->elf.sgotplt), - sec_addr (splt), plt_header); + ret = riscv_make_plt_header (output_bfd, + sec_addr (htab->elf.sgotplt), + sec_addr (splt), plt_header); + if (!ret) + return ret; for (i = 0; i < PLT_HEADER_INSNS; i++) bfd_put_32 (output_bfd, plt_header[i], splt->contents + 4*i);