public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64)
@ 2022-11-28  6:35 jiawei
  2022-11-28  7:50 ` Jan Beulich
  0 siblings, 1 reply; 4+ messages in thread
From: jiawei @ 2022-11-28  6:35 UTC (permalink / raw)
  To: binutils
  Cc: nelson, kito.cheng, palmer, christoph.muellner, philipp.tomsich,
	felixonmars, wuwei2016, jiawei

This adds support for efi-*-riscv64 by virtue of adding a new PEI target pei-
riscv64. This is not a full target and only exists to support EFI at 
this time.

This means that this target does not support relocation processing and is mostly
a container format.  This format has been added to elf based riscv64 targets
such that efi images can be made natively on Linux.

However this target is not valid for use with gas but only with objcopy.

With these changes the resulting file is recognized as an efi image.

Any magic number is based on the Microsoft PE specification [1].

[1] https://docs.microsoft.com/en-us/windows/win32/debug/pe-format

bfd/ChangeLog:

        * .gitignore: New.
        * Makefile.am: Add support.
        * Makefile.in: Ditto.
        * bfd.c (bfd_get_sign_extend_vma):  Add pei-riscv64.
        * coffcode.h (defined): Add riscv64 (riscv64_pei_vec) support.
        (__A_MAGIC_SET__): Ditto.
        * config.bfd: Ditto.
        * configure: Ditto.
        * configure.ac: Ditto.
        * libpei.h (GET_OPTHDR_IMAGE_BASE): New target.
        (PUT_OPTHDR_IMAGE_BASE): Ditto.
        (GET_OPTHDR_SIZE_OF_STACK_RESERVE): Ditto.
        (PUT_OPTHDR_SIZE_OF_STACK_RESERVE): Ditto.
        (GET_OPTHDR_SIZE_OF_STACK_COMMIT): Ditto.
        (PUT_OPTHDR_SIZE_OF_STACK_COMMIT): Ditto.
        (GET_OPTHDR_SIZE_OF_HEAP_RESERVE): Ditto.
        (PUT_OPTHDR_SIZE_OF_HEAP_RESERVE): Ditto.
        (GET_OPTHDR_SIZE_OF_HEAP_COMMIT): Ditto.
        (PUT_OPTHDR_SIZE_OF_HEAP_COMMIT): Ditto.
        (GET_PDATA_ENTRY): Ditto.
        (_bfd_XX_bfd_copy_private_bfd_data_common): Ditto.
        (_bfd_XX_bfd_copy_private_section_data): Ditto.
        (_bfd_XX_get_symbol_info): Ditto.
        (_bfd_XX_only_swap_filehdr_out): Ditto.
        (_bfd_XX_print_private_bfd_data_common): Ditto.
        (_bfd_XXi_final_link_postscript): Ditto.
        (_bfd_XXi_only_swap_filehdr_out): Ditto.
        (_bfd_XXi_swap_aouthdr_in): Ditto.
        (_bfd_XXi_swap_aouthdr_out): Ditto.
        (_bfd_XXi_swap_aux_in): Ditto.
        (_bfd_XXi_swap_aux_out): Ditto.
        (_bfd_XXi_swap_lineno_in): Ditto.
        (_bfd_XXi_swap_lineno_out): Ditto.
        (_bfd_XXi_swap_scnhdr_out): Ditto.
        (_bfd_XXi_swap_sym_in): Ditto.
        (_bfd_XXi_swap_sym_out): Ditto.
        (_bfd_XXi_swap_debugdir_in): Ditto.
        (_bfd_XXi_swap_debugdir_out): Ditto.
        (_bfd_XXi_write_codeview_record): Ditto.
        (_bfd_XXi_slurp_codeview_record): Ditto.
        (_bfd_peRISCV64_print_ce_compressed_pdata): Ditto.
        * peXXigen.c (defined): Support COFF_WITH_peRISCV64.
        * peicode.h (defined): Ditto.
        * targets.c: New target.
        * coff-riscv64.c: New file.
        * pei-riscv64.c: New file.

binutils/ChangeLog:

        * testsuite/binutils-all/riscv/pei-riscv64.d: New test.
        * testsuite/binutils-all/riscv/pei-riscv64.s: New test.

include/ChangeLog:

        * coff/pe.h (IMAGE_FILE_MACHINE_RISCV64): New target.
        * coff/riscv64.h: New file.

---
 bfd/.gitignore                                |   1 +
 bfd/Makefile.am                               |  10 +-
 bfd/Makefile.in                               |  11 +-
 bfd/bfd.c                                     |   1 +
 bfd/coff-riscv64.c                            | 170 ++++++++++++++++++
 bfd/coffcode.h                                |  19 +-
 bfd/config.bfd                                |   2 +-
 bfd/configure                                 |   1 +
 bfd/configure.ac                              |   1 +
 bfd/libpei.h                                  |  36 ++++
 bfd/peXXigen.c                                |  44 ++---
 bfd/pei-riscv64.c                             |  76 ++++++++
 bfd/peicode.h                                 |  20 ++-
 bfd/targets.c                                 |   2 +
 .../binutils-all/riscv/pei-riscv64.d          |  15 ++
 .../binutils-all/riscv/pei-riscv64.s          |  20 +++
 include/coff/pe.h                             |   1 +
 include/coff/riscv64.h                        |  62 +++++++
 18 files changed, 465 insertions(+), 27 deletions(-)
 create mode 100644 bfd/coff-riscv64.c
 create mode 100644 bfd/pei-riscv64.c
 create mode 100644 binutils/testsuite/binutils-all/riscv/pei-riscv64.d
 create mode 100644 binutils/testsuite/binutils-all/riscv/pei-riscv64.s
 create mode 100644 include/coff/riscv64.h

diff --git a/bfd/.gitignore b/bfd/.gitignore
index e93eb658453..b4955275cde 100644
--- a/bfd/.gitignore
+++ b/bfd/.gitignore
@@ -12,6 +12,7 @@
 /pex64igen.c
 /pe-aarch64igen.c
 /pe-loongarch64igen.c
+/pe-riscv64igen.c
 /stmp-bfd-h
 /targmatch.h
 
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index a88c6a0034d..bbd19edfa5d 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -578,11 +578,13 @@ BFD64_BACKENDS = \
 	mmo.lo \
 	pe-aarch64igen.lo \
 	pe-loongarch64igen.lo \
+	pe-riscv64igen.lo \
 	pe-x86_64.lo \
 	pei-aarch64.lo \
 	pe-aarch64.lo \
 	pei-ia64.lo \
 	pei-loongarch64.lo \
+	pei-riscv64.lo \
 	pei-x86_64.lo \
 	pepigen.lo \
 	pex64igen.lo \
@@ -627,6 +629,7 @@ BFD64_BACKENDS_CFILES = \
 	pei-aarch64.c \
 	pei-ia64.c \
 	pei-loongarch64.c \
+	pei-riscv64.c \
 	pei-x86_64.c \
 	vms-alpha.c
 
@@ -686,7 +689,8 @@ BUILD_CFILES = \
 	elf32-ia64.c elf64-ia64.c \
 	elf32-loongarch.c elf64-loongarch.c \
 	elf32-riscv.c elf64-riscv.c \
-	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c
+	peigen.c pepigen.c pex64igen.c \
+	pe-aarch64igen.c pe-loongarch64igen.c pe-riscv64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 
@@ -907,6 +911,10 @@ pe-loongarch64igen.c: peXXigen.c
 	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
 	$(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@
 
+pe-riscv64igen.c: peXXigen.c
+	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
+	$(AM_V_GEN)$(SED) -e s/XX/peRISCV64/g < $< >> $@
+
 host-aout.lo: Makefile
 
 # The following program can be used to generate a simple config file
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index d5cc5cb1e17..0ca67ba341f 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -1048,11 +1048,13 @@ BFD64_BACKENDS = \
 	mmo.lo \
 	pe-aarch64igen.lo \
 	pe-loongarch64igen.lo \
+	pe-riscv64igen.lo \
 	pe-x86_64.lo \
 	pei-aarch64.lo \
 	pe-aarch64.lo \
 	pei-ia64.lo \
 	pei-loongarch64.lo \
+	pei-riscv64.lo \
 	pei-x86_64.lo \
 	pepigen.lo \
 	pex64igen.lo \
@@ -1155,7 +1157,8 @@ BUILD_CFILES = \
 	elf32-ia64.c elf64-ia64.c \
 	elf32-loongarch.c elf64-loongarch.c \
 	elf32-riscv.c elf64-riscv.c \
-	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c
+	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c \
+	pe-loongarch64igen.c pe-riscv64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 SOURCE_HFILES = \
@@ -1710,6 +1713,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-arm.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-i386.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-loongarch64igen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-riscv64igen.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-mcore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-sh.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-x86_64.Plo@am__quote@
@@ -1720,6 +1724,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-i386.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-ia64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-loongarch64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-riscv64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-mcore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-sh.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-x86_64.Plo@am__quote@
@@ -2426,6 +2431,10 @@ pe-loongarch64igen.c: peXXigen.c
 	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
 	$(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@
 
+pe-riscv64igen.c: peXXigen.c
+	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
+	$(AM_V_GEN)$(SED) -e s/XX/peRISCV64/g < $< >> $@
+
 host-aout.lo: Makefile
 
 # The following program can be used to generate a simple config file
diff --git a/bfd/bfd.c b/bfd/bfd.c
index b9d4aa44d9c..17c296acba1 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1748,6 +1748,7 @@ bfd_get_sign_extend_vma (bfd *abfd)
       || strcmp (name, "pe-arm-wince-little") == 0
       || strcmp (name, "pei-arm-wince-little") == 0
       || strcmp (name, "pei-loongarch64") == 0
+      || strcmp (name, "pei-riscv64") == 0
       || strcmp (name, "aixcoff-rs6000") == 0
       || strcmp (name, "aix5coff64-rs6000") == 0)
     return 1;
diff --git a/bfd/coff-riscv64.c b/bfd/coff-riscv64.c
new file mode 100644
index 00000000000..b541a6c0daf
--- /dev/null
+++ b/bfd/coff-riscv64.c
@@ -0,0 +1,170 @@
+/* BFD back-end for LoongArch64 COFF files.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+
+#ifndef COFF_WITH_peRISCV64
+#define COFF_WITH_peRISCV64
+#endif
+
+/* Note we have to make sure not to include headers twice.
+   Not all headers are wrapped in #ifdef guards, so we define
+   PEI_HEADERS to prevent double including here.  */
+#ifndef PEI_HEADERS
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "coff/riscv64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+#include "libiberty.h"
+#endif
+
+#include "libcoff.h"
+
+/* The page size is a guess based on ELF.  */
+
+#define COFF_PAGE_SIZE 0x4000
+
+/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
+#define OCTETS_PER_BYTE(ABFD, SEC) 1
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET true
+#endif
+
+/* Currently we don't handle any relocations.  */
+static reloc_howto_type pe_riscv64_std_reloc_howto[] =
+  {
+
+  };
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER  2
+
+#ifndef NUM_ELEM
+#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
+#endif
+
+#define NUM_RELOCS NUM_ELEM (pe_riscv64_std_reloc_howto)
+
+#define RTYPE2HOWTO(cache_ptr, dst)             \
+  (cache_ptr)->howto = NULL
+
+#ifndef bfd_pe_print_pdata
+#define bfd_pe_print_pdata      NULL
+#endif
+
+/* Handle include/coff/riscv64.h external_reloc.  */
+#define SWAP_IN_RELOC_OFFSET	H_GET_32
+#define SWAP_OUT_RELOC_OFFSET	H_PUT_32
+
+/* Return TRUE if this relocation should
+   appear in the output .reloc section.  */
+
+static bool
+in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
+	    reloc_howto_type * howto)
+{
+  return !howto->pc_relative;
+}
+
+#include "coffcode.h"
+
+/* Target vectors.  */
+const bfd_target
+#ifdef TARGET_SYM
+  TARGET_SYM =
+#else
+  riscv64_pei_vec =
+#endif
+{
+#ifdef TARGET_NAME
+  TARGET_NAME,
+#else
+ "pei-riscv64",			/* Name.  */
+#endif
+  bfd_target_coff_flavour,
+  BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
+  BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
+
+  (HAS_RELOC | EXEC_P		/* Object flags.  */
+   | HAS_LINENO | HAS_DEBUG
+   | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
+#if defined(COFF_WITH_PE)
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
+#endif
+   | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
+
+#ifdef TARGET_UNDERSCORE
+  TARGET_UNDERSCORE,		/* Leading underscore.  */
+#else
+  0,				/* Leading underscore.  */
+#endif
+  '/',				/* Ar_pad_char.  */
+  15,				/* Ar_max_namelen.  */
+  0,				/* match priority.  */
+  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
+
+     /* Data conversion functions.  */
+     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
+     /* Header conversion functions.  */
+     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
+
+  /* Note that we allow an object file to be treated as a core file as well.  */
+  {				/* bfd_check_format.  */
+    _bfd_dummy_target,
+    coff_object_p,
+    bfd_generic_archive_p,
+    coff_object_p
+  },
+  {				/* bfd_set_format.  */
+    _bfd_bool_bfd_false_error,
+    coff_mkobject,
+    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error
+  },
+  {				/* bfd_write_contents.  */
+    _bfd_bool_bfd_false_error,
+    coff_write_object_contents,
+    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error
+  },
+
+  BFD_JUMP_TABLE_GENERIC (coff),
+  BFD_JUMP_TABLE_COPY (coff),
+  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+  BFD_JUMP_TABLE_SYMBOLS (coff),
+  BFD_JUMP_TABLE_RELOCS (coff),
+  BFD_JUMP_TABLE_WRITE (coff),
+  BFD_JUMP_TABLE_LINK (coff),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+
+  COFF_SWAP_TABLE
+};
+
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 52027981c3f..ed162f918df 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -2237,6 +2237,12 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr)
       machine = internal_f->f_flags & F_LOONGARCH64_ARCHITECTURE_MASK;
       break;
 #endif
+#ifdef RISCV64MAGIC
+    case RISCV64MAGIC:
+      arch = bfd_arch_riscv;
+      machine = internal_f->f_flags & F_RISCV64_ARCHITECTURE_MASK;
+      break;
+#endif
 #ifdef Z80MAGIC
     case Z80MAGIC:
       arch = bfd_arch_z80;
@@ -2807,6 +2813,12 @@ coff_set_flags (bfd * abfd,
       return true;
 #endif
 
+#ifdef RISCV64MAGIC
+    case bfd_arch_riscv:
+        * magicp = RISCV64MAGIC;
+	return true;
+#endif
+
 #ifdef ARMMAGIC
     case bfd_arch_arm:
 #ifdef ARM_WINCE
@@ -3902,7 +3914,7 @@ coff_write_object_contents (bfd * abfd)
     internal_f.f_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
 #endif
 
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
 #ifdef COFF_WITH_PE
   internal_f.f_flags |= IMAGE_FILE_32BIT_MACHINE;
 #else
@@ -3961,6 +3973,11 @@ coff_write_object_contents (bfd * abfd)
     internal_a.magic = ZMAGIC;
 #endif
 
+#if defined(RISCV64)
+#define __A_MAGIC_SET__
+    internal_a.magic = ZMAGIC;
+#endif
+
 #if defined MCORE_PE
 #define __A_MAGIC_SET__
     internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 0bc27fdce97..6377f413482 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -1223,7 +1223,7 @@ case "${targ}" in
     ;;
   riscv64*-*-*)
     targ_defvec=riscv_elf64_vec
-    targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec"
+    targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec riscv64_pei_vec"
     want64=true
     ;;
 #endif
diff --git a/bfd/configure b/bfd/configure
index 74bc5a18471..feeecc440bf 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13782,6 +13782,7 @@ do
     riscv_elf64_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
     riscv_elf32_be_vec)		 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
     riscv_elf64_be_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
+    riscv64_pei_vec)		 tb="$tb pei-riscv64.lo pe-riscv64igen.lo $coff"; 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 5d450a4ad25..e7c3e58d352 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -583,6 +583,7 @@ do
     riscv_elf64_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
     riscv_elf32_be_vec)		 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
     riscv_elf64_be_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
+    riscv64_pei_vec)		 tb="$tb pei-riscv64.lo pe-riscv64igen.lo $coff"; 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/libpei.h b/bfd/libpei.h
index 98e951d8839..cd1c7753f53 100644
--- a/bfd/libpei.h
+++ b/bfd/libpei.h
@@ -345,6 +345,41 @@
 #define _bfd_XXi_write_codeview_record			_bfd_peLoongArch64i_write_codeview_record
 #define _bfd_XXi_slurp_codeview_record			_bfd_peLoongArch64i_slurp_codeview_record
 
+#elif defined COFF_WITH_peRISCV64
+
+#define GET_OPTHDR_IMAGE_BASE		 H_GET_64
+#define PUT_OPTHDR_IMAGE_BASE		 H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_COMMIT	 H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT	 H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE	 H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE	 H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT	 H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT	 H_PUT_64
+#define GET_PDATA_ENTRY			 bfd_get_32
+
+#define _bfd_XX_bfd_copy_private_bfd_data_common	_bfd_peRISCV64_bfd_copy_private_bfd_data_common
+#define _bfd_XX_bfd_copy_private_section_data		_bfd_peRISCV64_bfd_copy_private_section_data
+#define _bfd_XX_get_symbol_info				_bfd_peRISCV64_get_symbol_info
+#define _bfd_XX_only_swap_filehdr_out			_bfd_peRISCV64_only_swap_filehdr_out
+#define _bfd_XX_print_private_bfd_data_common		_bfd_peRISCV64_print_private_bfd_data_common
+#define _bfd_XXi_final_link_postscript			_bfd_peRISCV64i_final_link_postscript
+#define _bfd_XXi_only_swap_filehdr_out			_bfd_peRISCV64i_only_swap_filehdr_out
+#define _bfd_XXi_swap_aouthdr_in			_bfd_peRISCV64i_swap_aouthdr_in
+#define _bfd_XXi_swap_aouthdr_out			_bfd_peRISCV64i_swap_aouthdr_out
+#define _bfd_XXi_swap_aux_in				_bfd_peRISCV64i_swap_aux_in
+#define _bfd_XXi_swap_aux_out				_bfd_peRISCV64i_swap_aux_out
+#define _bfd_XXi_swap_lineno_in				_bfd_peRISCV64i_swap_lineno_in
+#define _bfd_XXi_swap_lineno_out			_bfd_peRISCV64i_swap_lineno_out
+#define _bfd_XXi_swap_scnhdr_out			_bfd_peRISCV64i_swap_scnhdr_out
+#define _bfd_XXi_swap_sym_in				_bfd_peRISCV64i_swap_sym_in
+#define _bfd_XXi_swap_sym_out				_bfd_peRISCV64i_swap_sym_out
+#define _bfd_XXi_swap_debugdir_in			_bfd_peRISCV64i_swap_debugdir_in
+#define _bfd_XXi_swap_debugdir_out			_bfd_peRISCV64i_swap_debugdir_out
+#define _bfd_XXi_write_codeview_record			_bfd_peRISCV64i_write_codeview_record
+#define _bfd_XXi_slurp_codeview_record			_bfd_peRISCV64i_slurp_codeview_record
+
 #else /* !COFF_WITH_pep */
 
 #define GET_OPTHDR_IMAGE_BASE H_GET_32
@@ -443,5 +478,6 @@ bool _bfd_pe64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_pex64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_peAArch64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_peLoongArch64_print_ce_compressed_pdata (bfd *, void *);
+bool _bfd_peRISCV64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_pep_print_ce_compressed_pdata (bfd *, void *);
 
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 0232a63d558..33393bfec7c 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -61,8 +61,8 @@
    wasting too much time.  */
 
 /* This expands into COFF_WITH_pe, COFF_WITH_pep, COFF_WITH_pex64,
-   COFF_WITH_peAArch64 or COFF_WITH_peLoongArch64 depending on whether we're
-   compiling for straight PE or PE+.  */
+   COFF_WITH_peAArch64 ,COFF_WITH_peLoongArch64 or COFF_WITH_peRISCV64
+   depending on whether we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
 #include "sysdep.h"
@@ -88,6 +88,8 @@
 # include "coff/aarch64.h"
 #elif defined COFF_WITH_peLoongArch64
 # include "coff/loongarch64.h"
+#elif defined COFF_WITH_peRISCV64
+# include "coff/riscv64.h"
 #else
 # include "coff/i386.h"
 #endif
@@ -97,7 +99,7 @@
 #include "libpei.h"
 #include "safe-ctype.h"
 
-#if defined COFF_WITH_pep || defined COFF_WITH_pex64 || defined COFF_WITH_peAArch64 || defined COFF_WITH_peLoongArch64
+#if defined COFF_WITH_pep || defined COFF_WITH_pex64 || defined COFF_WITH_peAArch64 || defined COFF_WITH_peLoongArch64 || defined COFF_WITH_peRISCV64
 # undef AOUTSZ
 # define AOUTSZ		PEPAOUTSZ
 # define PEAOUTHDR	PEPAOUTHDR
@@ -474,7 +476,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
 
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -541,7 +543,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -549,12 +551,12 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -614,7 +616,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -622,7 +624,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -630,7 +632,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -744,7 +746,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
 			  aouthdr_out->standard.text_start);
 
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
 			  aouthdr_out->standard.data_start);
@@ -930,7 +932,7 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
     _bfd_error_handler (_("%pB:%.8s: section below image base"),
                         abfd, scnhdr_int->s_name);
   /* Do not compare lower 32-bits for 64-bit vma.  */
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   else if(ss != (ss & 0xffffffff))
     _bfd_error_handler (_("%pB:%.8s: RVA truncated"), abfd, scnhdr_int->s_name);
   PUT_SCNHDR_VADDR (abfd, ss & 0xffffffff, scnhdr_ext->s_vaddr);
@@ -1814,7 +1816,7 @@ pe_print_edata (bfd * abfd, void * vfile)
 static bool
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
 # define PDATA_ROW_SIZE	(3 * 8)
 #else
 # define PDATA_ROW_SIZE	(5 * 4)
@@ -1841,7 +1843,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
 
   fprintf (file,
 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   fprintf (file,
 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1878,7 +1880,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
       bfd_vma eh_handler;
       bfd_vma eh_data;
       bfd_vma prolog_end_addr;
-#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       int em_data;
 #endif
 
@@ -1896,7 +1898,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
 	/* We are probably into the padding of the section now.  */
 	break;
 
-#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       em_data = ((eh_handler & 0x1) << 2) | (prolog_end_addr & 0x3);
 #endif
       eh_handler &= ~(bfd_vma) 0x3;
@@ -1907,7 +1909,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
       bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file);
       bfd_fprintf_vma (abfd, file, end_addr); fputc (' ', file);
       bfd_fprintf_vma (abfd, file, eh_handler);
-#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       fputc (' ', file);
       bfd_fprintf_vma (abfd, file, eh_data); fputc (' ', file);
       bfd_fprintf_vma (abfd, file, prolog_end_addr);
@@ -2803,7 +2805,7 @@ _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile)
   bfd_fprintf_vma (abfd, file, i->AddressOfEntryPoint);
   fprintf (file, "\nBaseOfCode\t\t");
   bfd_fprintf_vma (abfd, file, i->BaseOfCode);
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have BaseOfData member!  */
   fprintf (file, "\nBaseOfData\t\t");
   bfd_fprintf_vma (abfd, file, i->BaseOfData);
@@ -3118,7 +3120,7 @@ _bfd_XX_get_symbol_info (bfd * abfd, asymbol *symbol, symbol_info *ret)
   coff_get_symbol_info (abfd, symbol, ret);
 }
 
-#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64))
+#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64))
 static int
 sort_x64_pdata (const void *l, const void *r)
 {
@@ -4537,7 +4539,7 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
 	the TLS data directory consists of 4 pointers, followed
 	by two 4-byte integer. This implies that the total size
 	is different for 32-bit and 64-bit executables.  */
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x18;
 #else
       pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x28;
@@ -4546,7 +4548,7 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
 
 /* If there is a .pdata section and we have linked pdata finally, we
      need to sort the entries ascending.  */
-#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64))
+#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64))
   {
     asection *sec = bfd_get_section_by_name (abfd, ".pdata");
 
diff --git a/bfd/pei-riscv64.c b/bfd/pei-riscv64.c
new file mode 100644
index 00000000000..69c16a2862f
--- /dev/null
+++ b/bfd/pei-riscv64.c
@@ -0,0 +1,76 @@
+/* BFD back-end for RISCV64 PE IMAGE COFF files.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#define TARGET_SYM		riscv64_pei_vec
+#define TARGET_NAME		"pei-riscv64"
+#define TARGET_ARCHITECTURE	bfd_arch_riscv
+#define TARGET_PAGESIZE		0x4000
+#define TARGET_BIG_ENDIAN	0
+#define TARGET_ARCHIVE		0
+#define TARGET_PRIORITY		0
+
+#define COFF_IMAGE_WITH_PE
+/* Rename the above into...  */
+#define COFF_WITH_peRISCV64
+#define COFF_WITH_PE
+#define PCRELOFFSET	   true
+
+/* Long section names not allowed in executable images, only object files.  */
+#define COFF_LONG_SECTION_NAMES 0
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#define PEI_HEADERS
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "coff/riscv64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+#include "libpei.h"
+#include "libiberty.h"
+
+/* Make sure we're setting a 64-bit format.  */
+#undef AOUTSZ
+#define AOUTSZ          PEPAOUTSZ
+#define PEAOUTHDR       PEPAOUTHDR
+
+#include "coff-riscv64.c"
+
diff --git a/bfd/peicode.h b/bfd/peicode.h
index f7ba24ae10a..b606210796e 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -233,7 +233,7 @@ coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
       /* Do not cut upper 32-bits for 64-bit vma.  */
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       scnhdr_int->s_vaddr &= 0xffffffff;
 #endif
     }
@@ -774,6 +774,16 @@ static const jump_table jtab[] =
     4, 0
   },
 
+#endif
+
+#ifdef RISCV64MAGIC
+/* We don't currently support jumping to DLLs, so if
+   someone does try emit a runtime trap.  Through BREAK 0.  */
+  { RISCV64MAGIC,
+    { 0x00, 0x00, 0x00, 0x00 },
+    4, 0
+  },
+
 #endif
 
   { 0, { 0 }, 0, 0 }
@@ -933,7 +943,7 @@ pe_ILF_build_a_bfd (bfd *	    abfd,
 	/* See PR 20907 for a reproducer.  */
 	goto error_return;
 
-#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       ((unsigned int *) id4->contents)[0] = ordinal;
       ((unsigned int *) id4->contents)[1] = 0x80000000;
       ((unsigned int *) id5->contents)[0] = ordinal;
@@ -1241,6 +1251,12 @@ pe_ILF_object_p (bfd * abfd)
 #endif
       break;
 
+    case IMAGE_FILE_MACHINE_RISCV64:
+#ifdef RISCV64MAGIC
+      magic = RISCV64MAGIC;
+#endif
+      break;
+
     case IMAGE_FILE_MACHINE_THUMB:
 #ifdef THUMBPEMAGIC
       {
diff --git a/bfd/targets.c b/bfd/targets.c
index 0bb85b64cc2..457b16e18ab 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -864,6 +864,7 @@ extern const bfd_target riscv_elf32_vec;
 extern const bfd_target riscv_elf64_vec;
 extern const bfd_target riscv_elf32_be_vec;
 extern const bfd_target riscv_elf64_be_vec;
+extern const bfd_target riscv64_pei_vec;
 extern const bfd_target rl78_elf32_vec;
 extern const bfd_target rs6000_xcoff64_vec;
 extern const bfd_target rs6000_xcoff64_aix_vec;
@@ -1258,6 +1259,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&riscv_elf64_vec,
 	&riscv_elf32_be_vec,
 	&riscv_elf64_be_vec,
+	&riscv64_pei_vec,
 #endif
 	&rl78_elf32_vec,
 
diff --git a/binutils/testsuite/binutils-all/riscv/pei-riscv64.d b/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
new file mode 100644
index 00000000000..bc170ef020d
--- /dev/null
+++ b/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
@@ -0,0 +1,15 @@
+#ld: -e0
+#PROG: objcopy
+#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --target=pei-riscv64
+#objdump: -h -f
+#name: Check if efi app format is recognized
+
+.*:     file format pei-riscv64
+architecture: riscv, flags 0x00000132:
+EXEC_P, HAS_SYMS, HAS_LOCALS, D_PAGED
+start address 0x0000000000000000
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.text         00000010  0[^ ]+  0[^ ]+  0[^ ]+  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
diff --git a/binutils/testsuite/binutils-all/riscv/pei-riscv64.s b/binutils/testsuite/binutils-all/riscv/pei-riscv64.s
new file mode 100644
index 00000000000..a2ac0352fd1
--- /dev/null
+++ b/binutils/testsuite/binutils-all/riscv/pei-riscv64.s
@@ -0,0 +1,20 @@
+        .file   "test_pei.c"
+        .option nopic
+        .attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
+        .attribute unaligned_access, 0
+        .attribute stack_align, 16
+        .text
+        .align  1
+        .globl  main
+        .type   main, @function
+main:
+        addi    sp,sp,-16
+        sd      s0,8(sp)
+        addi    s0,sp,16
+        li      a5,0
+        mv      a0,a5
+        ld      s0,8(sp)
+        addi    sp,sp,16
+        jr      ra
+        .size   main, .-main
+        .ident  "GCC: (gf120196382a) 13.0.0 20221124 (experimental)"
diff --git a/include/coff/pe.h b/include/coff/pe.h
index da600e1c781..6d68b8afe50 100644
--- a/include/coff/pe.h
+++ b/include/coff/pe.h
@@ -164,6 +164,7 @@
 #define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169
 #define IMAGE_FILE_MACHINE_AMD64             0x8664
 #define IMAGE_FILE_MACHINE_LOONGARCH64       0x6264
+#define IMAGE_FILE_MACHINE_RISCV64           0x5064
 
 #define IMAGE_SUBSYSTEM_UNKNOWN			 0
 #define IMAGE_SUBSYSTEM_NATIVE			 1
diff --git a/include/coff/riscv64.h b/include/coff/riscv64.h
new file mode 100644
index 00000000000..0eb3a40690a
--- /dev/null
+++ b/include/coff/riscv64.h
@@ -0,0 +1,62 @@
+/* RISCV64 COFF support for BFD.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#define COFFRISCV64 1
+
+#define L_LNNO_SIZE 2
+#define INCLUDE_COMDAT_FIELDS_IN_AUXENT
+#include "coff/external.h"
+
+#define F_RISCV64_ARCHITECTURE_MASK	(0x4000)
+
+#define RISCV64MAGIC	0x5064  /* From Microsoft specification. */
+
+#undef  BADMAG
+#define BADMAG(x) ((x).f_magic != RISCV64MAGIC)
+#define RISCV64         1                 /* Customize coffcode.h.  */
+
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b
+
+#define OMAGIC          0404    /* Object files, eg as output.  */
+#define ZMAGIC          IMAGE_NT_OPTIONAL_HDR64_MAGIC    /* Demand load format, eg normal ld output 0x10b.  */
+#define STMAGIC		0401	/* Target shlib.  */
+#define SHMAGIC		0443	/* Host   shlib.  */
+
+/* define some NT default values */
+/*  #define NT_IMAGE_BASE        0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT    0x200
+#define NT_DEF_RESERVE       0x100000
+#define NT_DEF_COMMIT        0x1000
+
+/* We use the .rdata section to hold read only data.  */
+#define _LIT	".rdata"
+
+/********************** RELOCATION DIRECTIVES **********************/
+struct external_reloc
+{
+  char r_vaddr[4];
+  char r_symndx[4];
+  char r_type[2];
+  char r_offset[4];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 14
+
-- 
2.25.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64)
  2022-11-28  6:35 [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64) jiawei
@ 2022-11-28  7:50 ` Jan Beulich
  2022-11-28 15:08   ` jiawei
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Beulich @ 2022-11-28  7:50 UTC (permalink / raw)
  To: jiawei
  Cc: nelson, kito.cheng, palmer, christoph.muellner, philipp.tomsich,
	felixonmars, wuwei2016, binutils

On 28.11.2022 07:35, jiawei wrote:
> This adds support for efi-*-riscv64 by virtue of adding a new PEI target pei-
> riscv64. This is not a full target and only exists to support EFI at 
> this time.

Just some general remarks below; I haven't looked at the changes
themselves, yet (and I also can't promise I would get to doing so any
time soon).

> This means that this target does not support relocation processing and is mostly
> a container format.  This format has been added to elf based riscv64 targets
> such that efi images can be made natively on Linux.

Hmm, I have reservations (not just for RISC-V) against this objcopy-only
model. It would imo be better if ld was made capable of producing EFI
binaries (and then likely also other PE ones) from ELF input, like is
possible for at least some other targets (e.g. x86).

Furthermore I also question the usefulness of conversion without reloc
handling. This may help with images built into firmware, but anything
you can load at runtime may not be loadable at all if the address range
it was linked for is occupied or otherwise unavailable, and if the
image cannot be relocated because relocations were stripped (and the
image is marked accordingly).

> However this target is not valid for use with gas but only with objcopy.

I guess you mean ld, not gas here? PE is an executable file format after all,
not an object file one. It would be COFF there ...

Jan

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Re: [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64)
  2022-11-28  7:50 ` Jan Beulich
@ 2022-11-28 15:08   ` jiawei
  2022-11-28 17:48     ` Palmer Dabbelt
  0 siblings, 1 reply; 4+ messages in thread
From: jiawei @ 2022-11-28 15:08 UTC (permalink / raw)
  To: Jan Beulich
  Cc: nelson, kito.cheng, palmer, christoph.muellner, philipp.tomsich,
	felixonmars, wuwei2016, binutils




&gt; -----原始邮件-----
&gt; 发件人: "Jan Beulich" <jbeulich@suse.com>
&gt; 发送时间: 2022-11-28 15:50:12 (星期一)
&gt; 收件人: jiawei <jiawei@iscas.ac.cn>
&gt; 抄送: nelson@rivosinc.com, kito.cheng@sifive.com, palmer@rivosinc.com, christoph.muellner@vrull.eu, philipp.tomsich@vrull.eu, felixonmars@archlinux.org, wuwei2016@iscas.ac.cn, binutils@sourceware.org
&gt; 主题: Re: [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64)
&gt; 
&gt; On 28.11.2022 07:35, jiawei wrote:
&gt; &gt; This adds support for efi-*-riscv64 by virtue of adding a new PEI target pei-
&gt; &gt; riscv64. This is not a full target and only exists to support EFI at 
&gt; &gt; this time.
&gt; 
&gt; Just some general remarks below; I haven't looked at the changes
&gt; themselves, yet (and I also can't promise I would get to doing so any
&gt; time soon).
&gt; 
&gt; &gt; This means that this target does not support relocation processing and is mostly
&gt; &gt; a container format.  This format has been added to elf based riscv64 targets
&gt; &gt; such that efi images can be made natively on Linux.
&gt; 
&gt; Hmm, I have reservations (not just for RISC-V) against this objcopy-only
&gt; model. It would imo be better if ld was made capable of producing EFI
&gt; binaries (and then likely also other PE ones) from ELF input, like is
&gt; possible for at least some other targets (e.g. x86).
&gt; 
&gt; Furthermore I also question the usefulness of conversion without reloc
&gt; handling. This may help with images built into firmware, but anything
&gt; you can load at runtime may not be loadable at all if the address range
&gt; it was linked for is occupied or otherwise unavailable, and if the
&gt; image cannot be relocated because relocations were stripped (and the
&gt; image is marked accordingly).

Thanks for your comments, you are right, I think this only a partial 

implement for efistub support: 

https://man.archlinux.org/man/core/systemd/linuxaa64.efi.stub.7.en

&gt; 
&gt; &gt; However this target is not valid for use with gas but only with objcopy.
&gt; 
&gt; I guess you mean ld, not gas here? PE is an executable file format after all,
&gt; not an object file one. It would be COFF there ...
&gt; 
&gt; Jan

Yes, it just mean it can verify with using objdump. Added a testcase to verify
that if we can use target 'pei-riscv'.


</jiawei@iscas.ac.cn></jbeulich@suse.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Re: [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64)
  2022-11-28 15:08   ` jiawei
@ 2022-11-28 17:48     ` Palmer Dabbelt
  0 siblings, 0 replies; 4+ messages in thread
From: Palmer Dabbelt @ 2022-11-28 17:48 UTC (permalink / raw)
  To: jiawei
  Cc: jbeulich, nelson, kito.cheng, christoph.muellner,
	philipp.tomsich, felixonmars, wuwei2016, binutils

On Mon, 28 Nov 2022 07:08:05 PST (-0800), jiawei@iscas.ac.cn wrote:
>
>
>
> &gt; -----原始邮件-----
> &gt; 发件人: "Jan Beulich" <jbeulich@suse.com>
> &gt; 发送时间: 2022-11-28 15:50:12 (星期一)
> &gt; 收件人: jiawei <jiawei@iscas.ac.cn>
> &gt; 抄送: nelson@rivosinc.com, kito.cheng@sifive.com, palmer@rivosinc.com, christoph.muellner@vrull.eu, philipp.tomsich@vrull.eu, felixonmars@archlinux.org, wuwei2016@iscas.ac.cn, binutils@sourceware.org
> &gt; 主题: Re: [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64)
> &gt; 
> &gt; On 28.11.2022 07:35, jiawei wrote:
> &gt; &gt; This adds support for efi-*-riscv64 by virtue of adding a new PEI target pei-
> &gt; &gt; riscv64. This is not a full target and only exists to support EFI at 
> &gt; &gt; this time.
> &gt; 
> &gt; Just some general remarks below; I haven't looked at the changes
> &gt; themselves, yet (and I also can't promise I would get to doing so any
> &gt; time soon).
> &gt; 
> &gt; &gt; This means that this target does not support relocation processing and is mostly
> &gt; &gt; a container format.  This format has been added to elf based riscv64 targets
> &gt; &gt; such that efi images can be made natively on Linux.
> &gt; 
> &gt; Hmm, I have reservations (not just for RISC-V) against this objcopy-only
> &gt; model. It would imo be better if ld was made capable of producing EFI
> &gt; binaries (and then likely also other PE ones) from ELF input, like is
> &gt; possible for at least some other targets (e.g. x86).
> &gt; 
> &gt; Furthermore I also question the usefulness of conversion without reloc
> &gt; handling. This may help with images built into firmware, but anything
> &gt; you can load at runtime may not be loadable at all if the address range
> &gt; it was linked for is occupied or otherwise unavailable, and if the
> &gt; image cannot be relocated because relocations were stripped (and the
> &gt; image is marked accordingly).
>
> Thanks for your comments, you are right, I think this only a partial 
>
> implement for efistub support: 
>
> https://man.archlinux.org/man/core/systemd/linuxaa64.efi.stub.7.en

I'm not exactly sure what's going on here, but at least in Linux we can 
already produce integrated EFI stubs by putting a fake PE header into 
flat binaries.  That's very much a hack, but it sounds like this target 
would have all the same issues?

I suppose there's some use case for these fake-PE binaries as we're 
producing them from Linux, but as pointed out they're pretty fragile.  
I'm not sure it's a net benefit to have a target that generates them -- 
I guess if this errors out when trying to generate any PE it can't 
handle then at least there's some protection from users shooting 
themselves in the foot, but I haven't read the code in enough detail to 
know that's the case.

That said, it seems entirely sane to just wait for a full PE 
implementation before merging the code.

> &gt; 
> &gt; &gt; However this target is not valid for use with gas but only with objcopy.
> &gt; 
> &gt; I guess you mean ld, not gas here? PE is an executable file format after all,
> &gt; not an object file one. It would be COFF there ...
> &gt; 
> &gt; Jan
>
> Yes, it just mean it can verify with using objdump. Added a testcase to verify
> that if we can use target 'pei-riscv'.
>
>
> </jiawei@iscas.ac.cn></jbeulich@suse.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-11-28 17:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-28  6:35 [PATCH] RISC-V: Add support for RISCV64 EFI(efi-*-riscv64) jiawei
2022-11-28  7:50 ` Jan Beulich
2022-11-28 15:08   ` jiawei
2022-11-28 17:48     ` Palmer Dabbelt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).