RISC-V: Give error for RVE PLTs.

Message ID 20180925201504.29878-1-jimw@sifive.com
State New
Headers show
Series
  • RISC-V: Give error for RVE PLTs.
Related show

Commit Message

Jim Wilson Sept. 25, 2018, 8:15 p.m.
The standard PLT instruction sequence uses 4 temporary registers, but the RVE
base architecture only has 3, so this can't work.  However, there is no
expectation that Linux or shared libraries will ever support RVE, so we should
just give an error for this.  This is patterned after a similar error in the
ARM port for Thumb-1 PLTs.

Tested with rv32i and rv32e newlib and linux toolchain builds.  The rv32e linux
build produces the expected error, after I hacked up glibc so it would build
for RVE.  The other ones continue to work without error.  Also tested with the
usual sanity check of riscv{32,64}-{elf,linux} binutils make check, with no
regressions.

Committed.

Jim

	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/elfnn-riscv.c | 44 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 8 deletions(-)

-- 
2.17.1

Patch

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index f3e2cc7c37..c99bcff5f1 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);