ld: Add elf{32,64}[lb]riscv_fbsd emulations and riscv{32,64}{,be}-*-freebsd* triples

Message ID 20210131070705.3475600-1-maskray@google.com
State New
Headers show
Series
  • ld: Add elf{32,64}[lb]riscv_fbsd emulations and riscv{32,64}{,be}-*-freebsd* triples
Related show

Commit Message

Nick Clifton via Binutils Jan. 31, 2021, 7:07 a.m.
Relax an ABI compatibility check so that ELFOSABI_FREEBSD output can
subsume ELFOSABI_NONE/ELFOSABI_GNU input object files.

    PR 27296
bfd/
    * config.bfd: Add riscvbe-*-freebsd*, riscv32be-*-freebsd*,
    riscv-*-freebsd*, riscv32*-*-freebsd*, riscv64be-*-freebsd*,
    riscv64*-*-freebsd*.
    * configure.ac: Add riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec,
    riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec.
    * elfnn-riscv.c (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME,
    TARGET_BIG_SYM, TARGET_BIG_NAME, ELF_OSABI, elf32_bed, elf64_bed):
    Define for freebsd.
    * targets.c (riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec,
    riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec): Declare.
    (_bfd_target_vector): Add them.
    * configure: Regenerate.
ld/
    * Makefile.am (ALL_EMULATION_SOURCES): Add eelf32lriscv_fbsd.c and
    eelf32briscv_fbsd.c.
    (ALL_64_EMULATION_SOURCES): Add eelf64lriscv_fbsd.c and
    eelf64briscv_fbsd.c.
    Include $(DEPDIR)/eelf*lriscv_fbsd* files.
    * configure.tgt: Add riscvbe-*-freebsd*, riscv32be-*-freebsd*,
    riscv-*-freebsd*, riscv32*-*-freebsd*, riscv64be-*-freebsd*,
    riscv64*-*-freebsd*.
    * emulparams/elf32lriscv_bsd.sh: New file.
    * emulparams/elf32briscv_bsd.sh: New file.
    * emulparams/elf64lriscv_bsd.sh: New file.
    * emulparams/elf64briscv_bsd.sh: New file.
    * Makefile.in: Regenerate.
    * po/BLD-POTFILES.in: Regenerate.
---
 bfd/config.bfd                    | 20 +++++++++++++++
 bfd/configure                     |  4 +++
 bfd/configure.ac                  |  4 +++
 bfd/elfnn-riscv.c                 | 41 ++++++++++++++++++++++++-------
 bfd/targets.c                     |  8 ++++++
 ld/Makefile.am                    |  7 ++++++
 ld/Makefile.in                    |  8 ++++++
 ld/configure.tgt                  | 17 +++++++++++++
 ld/emulparams/elf32briscv_fbsd.sh |  4 +++
 ld/emulparams/elf32lriscv_fbsd.sh |  4 +++
 ld/emulparams/elf64briscv_fbsd.sh |  4 +++
 ld/emulparams/elf64lriscv_fbsd.sh |  4 +++
 ld/po/BLD-POTFILES.in             |  4 +++
 13 files changed, 120 insertions(+), 9 deletions(-)
 create mode 100644 ld/emulparams/elf32briscv_fbsd.sh
 create mode 100644 ld/emulparams/elf32lriscv_fbsd.sh
 create mode 100644 ld/emulparams/elf64briscv_fbsd.sh
 create mode 100644 ld/emulparams/elf64lriscv_fbsd.sh

-- 
2.30.0.365.g02bc693789-goog

Comments

Nelson Chu Feb. 1, 2021, 6:14 a.m. | #1
Hi Maskray

Thanks for adding this support, I have some thoughts and suggestions.

On Sun, Jan 31, 2021 at 3:07 PM Fangrui Song <maskray@google.com> wrote:
>

> Relax an ABI compatibility check so that ELFOSABI_FREEBSD output can

> subsume ELFOSABI_NONE/ELFOSABI_GNU input object files.

>

>     PR 27296

> bfd/

>     * config.bfd: Add riscvbe-*-freebsd*, riscv32be-*-freebsd*,

>     riscv-*-freebsd*, riscv32*-*-freebsd*, riscv64be-*-freebsd*,

>     riscv64*-*-freebsd*.

>     * configure.ac: Add riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec,

>     riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec.

>     * elfnn-riscv.c (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME,

>     TARGET_BIG_SYM, TARGET_BIG_NAME, ELF_OSABI, elf32_bed, elf64_bed):

>     Define for freebsd.

>     * targets.c (riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec,

>     riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec): Declare.

>     (_bfd_target_vector): Add them.

>     * configure: Regenerate.

> ld/

>     * Makefile.am (ALL_EMULATION_SOURCES): Add eelf32lriscv_fbsd.c and

>     eelf32briscv_fbsd.c.

>     (ALL_64_EMULATION_SOURCES): Add eelf64lriscv_fbsd.c and

>     eelf64briscv_fbsd.c.

>     Include $(DEPDIR)/eelf*lriscv_fbsd* files.

>     * configure.tgt: Add riscvbe-*-freebsd*, riscv32be-*-freebsd*,

>     riscv-*-freebsd*, riscv32*-*-freebsd*, riscv64be-*-freebsd*,

>     riscv64*-*-freebsd*.

>     * emulparams/elf32lriscv_bsd.sh: New file.

>     * emulparams/elf32briscv_bsd.sh: New file.

>     * emulparams/elf64lriscv_bsd.sh: New file.

>     * emulparams/elf64briscv_bsd.sh: New file.

>     * Makefile.in: Regenerate.

>     * po/BLD-POTFILES.in: Regenerate.


I think we also need to add the FreeBSD support for RISC-V assembler.
After scanning other targets' code quickly, we can set the em=freebsd
in the gas/configure.tgt for target riscv*-*-freebsd*, then the
TE_FreeBSD will be defined, and we should update the
riscv_target_format (gas/config/tc-riscv.c) to output the right format
name.  You can refer to what MIPS did in their mips_target_format
(gas/config/tc-mips.c).

> diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c

> index b2ec6a29fbf..98918b29f4e 100644

> --- a/bfd/elfnn-riscv.c

> +++ b/bfd/elfnn-riscv.c

> @@ -3786,15 +3786,6 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)

>    if (!is_riscv_elf (ibfd) || !is_riscv_elf (obfd))

>      return TRUE;

>

> -  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)

> -    {

> -      (*_bfd_error_handler)

> -       (_("%pB: ABI is incompatible with that of the selected emulation:\n"

> -          "  target emulation `%s' does not match `%s'"),

> -        ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));

> -      return FALSE;

> -    }

> -

>    if (!_bfd_elf_merge_object_attributes (ibfd, info))

>      return FALSE;

>

> @@ -3811,6 +3802,18 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)

>        return TRUE;

>      }

>

> +  if (elf_elfheader (ibfd)->e_ident[EI_CLASS]

> +         != elf_elfheader (obfd)->e_ident[EI_CLASS]

> +      || elf_elfheader (ibfd)->e_ident[EI_DATA]

> +            != elf_elfheader (obfd)->e_ident[EI_DATA])


Indent needs to be fixed, it's minor

> +    {

> +      (*_bfd_error_handler)

> +       (_("%pB: ABI is incompatible with that of the selected emulation:\n"

> +          "  target emulation `%s' does not match `%s'"),

> +        ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));

> +      return FALSE;

> +    }

> +


This change broke the GNU linker, I get lots of errors as follows when
just compiling a simple HelloWorld,

/scratch/nelsonc/build-upstream/rv32i-elf/build-install/lib/gcc/riscv32-unknown-elf/10.2.0/../../../../riscv32-unknown-elf/bin/ld:
/scratch/nelsonc/build-upstream/rv32i-elf/build-install/lib/gcc/riscv32-unknown-elf/10.2.0/crtbegin.o:
ABI is incompatible with that of the selected emulation:
  target emulation `elf32-littleriscv' does not match `elf32-littleriscv'
/scratch/nelsonc/build-upstream/rv32i-elf/build-install/lib/gcc/riscv32-unknown-elf/10.2.0/../../../../riscv32-unknown-elf/bin/ld:
failed to merge target specific data of file
/scratch/nelsonc/build-upstream/rv32i-elf/build-install/lib/gcc/riscv32-unknown-elf/10.2.0/crtbegin.o
/scratch/nelsonc/build-upstream/rv32i-elf/build-install/lib/gcc/riscv32-unknown-elf/10.2.0/../../../../riscv32-unknown-elf/bin/ld:
/tmp/ccY5Ib0n.o: ABI is incompatible with that of the selected
emulation:
  target emulation `elf32-littleriscv' does not match `elf32-littleriscv'

The problem is that we just handle/copy the e_flags here when
elf_flags_init (obfd) is FALSE, the correct elf header CLASS/DATA are
set until _bfd_elf_init_file_header in bfd/elf.c, not here.
Therefore, you are comparing an uninitialized elf header CLASS/DATA
from the output bfd with the input bfd which is aleady set.  I suppose
you should remain the original check in the
_bfd_riscv_elf_merge_private_bfd_data.  Adding the related FreeBSD
support in the assembler should let linker can get the correct
elf32-littleriscv-freebsd target name by bfd_get_target, rather than
get the elf32-littleriscv for freebsd.  Besides, we also need to
update the riscv_elf_object_p, to recognize the freebsd targets.

Otherwise, this patch should be fine and won't affect our current
elf/linux toolchains.  I have tested the rv32i-newlib and rv64gc-glibc
toolchains quickly, the gcc/binutils regressions look fine so far.
For safety, I hope we can pass the whole riscv-gnu-toolchain
regressions for the later fixed patches.

Thanks
Nelson
Jessica Clarke Feb. 2, 2021, 3:17 a.m. | #2
On Sat, Jan 30, 2021 at 11:07:05PM -0800, Fangrui Song wrote:
> Relax an ABI compatibility check so that ELFOSABI_FREEBSD output can

> subsume ELFOSABI_NONE/ELFOSABI_GNU input object files.

>

>     PR 27296

> bfd/

>     * config.bfd: Add riscvbe-*-freebsd*, riscv32be-*-freebsd*,

>     riscv-*-freebsd*, riscv32*-*-freebsd*, riscv64be-*-freebsd*,

>     riscv64*-*-freebsd*.

>     * configure.ac: Add riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec,

>     riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec.

>     * elfnn-riscv.c (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME,

>     TARGET_BIG_SYM, TARGET_BIG_NAME, ELF_OSABI, elf32_bed, elf64_bed):

>     Define for freebsd.

>     * targets.c (riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec,

>     riscv_elf32_fbsd_vec, riscv_elf32_fbsd_vec): Declare.

>     (_bfd_target_vector): Add them.

>     * configure: Regenerate.

> ld/

>     * Makefile.am (ALL_EMULATION_SOURCES): Add eelf32lriscv_fbsd.c and

>     eelf32briscv_fbsd.c.

>     (ALL_64_EMULATION_SOURCES): Add eelf64lriscv_fbsd.c and

>     eelf64briscv_fbsd.c.

>     Include $(DEPDIR)/eelf*lriscv_fbsd* files.

>     * configure.tgt: Add riscvbe-*-freebsd*, riscv32be-*-freebsd*,

>     riscv-*-freebsd*, riscv32*-*-freebsd*, riscv64be-*-freebsd*,

>     riscv64*-*-freebsd*.

>     * emulparams/elf32lriscv_bsd.sh: New file.

>     * emulparams/elf32briscv_bsd.sh: New file.

>     * emulparams/elf64lriscv_bsd.sh: New file.

>     * emulparams/elf64briscv_bsd.sh: New file.

>     * Makefile.in: Regenerate.

>     * po/BLD-POTFILES.in: Regenerate.


As FreeBSD and LLVM developers, and as dicussed on IRC, we do not
believe the emulations are needed, as FreeBSD has been using ELF notes
to brand executables for many years rather than the inflexible EI_OSABI.
AArch64 does not use an _fbsd emulation with an LLVM toolchain (though
for some unknown reason, likely not understanding the situation, BFD did
gain one for it), and I do not think there is a need to pollute RISC-V
with such legacy junk.

Jess

Patch

diff --git a/bfd/config.bfd b/bfd/config.bfd
index e7b55b0dd78..40d08522a8e 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -1158,21 +1158,41 @@  case "${targ}" in
     ;;
 
 #ifdef BFD64
+  riscvbe-*-freebsd* | riscv32be*-*-freebsd*)
+    targ_defvec=riscv_elf32_fbsd_be_vec
+    targ_selvecs="riscv_elf32_vec riscv_elf32_be_vec riscv_elf64_vec riscv_elf64_be_vec riscv_elf32_fbsd_vec riscv_elf32_fbsd_be_vec riscv_elf64_fbsd_vec riscv_elf64_fbsd_be_vec"
+    want64=true
+    ;;
   riscvbe-*-* | riscv32be*-*-*)
     targ_defvec=riscv_elf32_be_vec
     targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec"
     want64=true
     ;;
+  riscv-*-freebsd* | riscv32*-*-freebsd*)
+    targ_defvec=riscv_elf32_fbsd_vec
+    targ_selvecs="riscv_elf32_vec riscv_elf32_be_vec riscv_elf64_vec riscv_elf64_be_vec riscv_elf32_fbsd_vec riscv_elf32_fbsd_be_vec riscv_elf64_fbsd_vec riscv_elf64_fbsd_be_vec"
+    want64=true
+    ;;
   riscv-*-* | riscv32*-*-*)
     targ_defvec=riscv_elf32_vec
     targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec"
     want64=true
     ;;
+  riscv64be*-*-freebsd*)
+    targ_defvec=riscv_elf64_fbsd_be_vec
+    targ_selvecs="riscv_elf32_vec riscv_elf32_be_vec riscv_elf64_vec riscv_elf64_be_vec riscv_elf32_fbsd_vec riscv_elf32_fbsd_be_vec riscv_elf64_fbsd_vec riscv_elf64_fbsd_be_vec"
+    want64=true
+    ;;
   riscv64be*-*-*)
     targ_defvec=riscv_elf64_be_vec
     targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec"
     want64=true
     ;;
+  riscv64*-*-freebsd*)
+    targ_defvec=riscv_elf64_fbsd_vec
+    targ_selvecs="riscv_elf32_vec riscv_elf32_be_vec riscv_elf64_vec riscv_elf64_be_vec riscv_elf32_fbsd_vec riscv_elf32_fbsd_be_vec riscv_elf64_fbsd_vec riscv_elf64_fbsd_be_vec"
+    want64=true
+    ;;
   riscv64*-*-*)
     targ_defvec=riscv_elf64_vec
     targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec"
diff --git a/bfd/configure b/bfd/configure
index ed328de6e9f..ee3e2e81989 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -14942,6 +14942,10 @@  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 ;;
+    riscv_elf32_fbsd_vec)	 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
+    riscv_elf64_fbsd_vec)	 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
+    riscv_elf32_fbsd_be_vec)	 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
+    riscv_elf64_fbsd_be_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 102a22171f6..a961037262f 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -627,6 +627,10 @@  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 ;;
+    riscv_elf32_fbsd_vec)	 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
+    riscv_elf64_fbsd_vec)	 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
+    riscv_elf32_fbsd_be_vec)	 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
+    riscv_elf64_fbsd_be_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 b2ec6a29fbf..98918b29f4e 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3786,15 +3786,6 @@  _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   if (!is_riscv_elf (ibfd) || !is_riscv_elf (obfd))
     return TRUE;
 
-  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
-    {
-      (*_bfd_error_handler)
-	(_("%pB: ABI is incompatible with that of the selected emulation:\n"
-	   "  target emulation `%s' does not match `%s'"),
-	 ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
-      return FALSE;
-    }
-
   if (!_bfd_elf_merge_object_attributes (ibfd, info))
     return FALSE;
 
@@ -3811,6 +3802,18 @@  _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
       return TRUE;
     }
 
+  if (elf_elfheader (ibfd)->e_ident[EI_CLASS]
+	  != elf_elfheader (obfd)->e_ident[EI_CLASS]
+      || elf_elfheader (ibfd)->e_ident[EI_DATA]
+	     != elf_elfheader (obfd)->e_ident[EI_DATA])
+    {
+      (*_bfd_error_handler)
+	(_("%pB: ABI is incompatible with that of the selected emulation:\n"
+	   "  target emulation `%s' does not match `%s'"),
+	 ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
+      return FALSE;
+    }
+
   /* Check to see if the input BFD actually contains any sections.  If not,
      its flags may not have been initialized either, but it cannot actually
      cause any incompatibility.  Do not short-circuit dynamic objects; their
@@ -5028,3 +5031,23 @@  riscv_elf_obj_attrs_arg_type (int tag)
 #define elf_backend_obj_attrs_section		".riscv.attributes"
 
 #include "elfNN-target.h"
+
+#undef  TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM riscv_elfNN_fbsd_vec
+#undef  TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME "elfNN-littleriscv-freebsd"
+
+#undef  TARGET_BIG_SYM
+#define TARGET_BIG_SYM riscv_elfNN_fbsd_be_vec
+#undef  TARGET_BIG_NAME
+#define TARGET_BIG_NAME "elfNN-bigriscv-freebsd"
+
+#undef  ELF_OSABI
+#define ELF_OSABI ELFOSABI_FREEBSD
+
+#undef  elf32_bed
+#define elf32_bed elf32_fbsd_bed
+#undef  elf64_bed
+#define elf64_bed elf64_fbsd_bed
+
+#include "elfNN-target.h"
diff --git a/bfd/targets.c b/bfd/targets.c
index 076441b3a21..480cc2cb53c 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -859,6 +859,10 @@  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 riscv_elf32_fbsd_vec;
+extern const bfd_target riscv_elf64_fbsd_vec;
+extern const bfd_target riscv_elf32_fbsd_be_vec;
+extern const bfd_target riscv_elf64_fbsd_be_vec;
 extern const bfd_target rl78_elf32_vec;
 extern const bfd_target rs6000_xcoff64_vec;
 extern const bfd_target rs6000_xcoff64_aix_vec;
@@ -1255,6 +1259,10 @@  static const bfd_target * const _bfd_target_vector[] =
 	&riscv_elf64_vec,
 	&riscv_elf32_be_vec,
 	&riscv_elf64_be_vec,
+	&riscv_elf32_fbsd_vec,
+	&riscv_elf64_fbsd_vec,
+	&riscv_elf32_fbsd_be_vec,
+	&riscv_elf64_fbsd_be_vec,
 #endif
 	&rl78_elf32_vec,
 
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 2c9a487335c..8aa8abcee50 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -266,9 +266,11 @@  ALL_EMULATION_SOURCES = \
 	eelf32lriscv.c \
 	eelf32lriscv_ilp32f.c \
 	eelf32lriscv_ilp32.c \
+	eelf32lriscv_fbsd.c \
 	eelf32briscv.c \
 	eelf32briscv_ilp32f.c \
 	eelf32briscv_ilp32.c \
+	eelf32briscv_fbsd.c \
 	eelf32rl78.c \
 	eelf32rx.c \
 	eelf32rx_linux.c \
@@ -438,9 +440,11 @@  ALL_64_EMULATION_SOURCES = \
 	eelf64lriscv.c \
 	eelf64lriscv_lp64f.c \
 	eelf64lriscv_lp64.c \
+	eelf64lriscv_fbsd.c \
 	eelf64briscv.c \
 	eelf64briscv_lp64f.c \
 	eelf64briscv_lp64.c \
+	eelf64briscv_fbsd.c \
 	eelf64ltsmip.c \
 	eelf64ltsmip_fbsd.c \
 	eelf64mmix.c \
@@ -760,6 +764,7 @@  $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Pc@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx_linux.Pc@am__quote@
@@ -925,9 +930,11 @@  $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Pc@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Pc@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Pc@am__quote@
diff --git a/ld/Makefile.in b/ld/Makefile.in
index ab8f23a2c0f..6bddb7802bb 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -756,9 +756,11 @@  ALL_EMULATION_SOURCES = \
 	eelf32lriscv.c \
 	eelf32lriscv_ilp32f.c \
 	eelf32lriscv_ilp32.c \
+	eelf32lriscv_fbsd.c \
 	eelf32briscv.c \
 	eelf32briscv_ilp32f.c \
 	eelf32briscv_ilp32.c \
+	eelf32briscv_fbsd.c \
 	eelf32rl78.c \
 	eelf32rx.c \
 	eelf32rx_linux.c \
@@ -927,9 +929,11 @@  ALL_64_EMULATION_SOURCES = \
 	eelf64lriscv.c \
 	eelf64lriscv_lp64f.c \
 	eelf64lriscv_lp64.c \
+	eelf64lriscv_fbsd.c \
 	eelf64briscv.c \
 	eelf64briscv_lp64f.c \
 	eelf64briscv_lp64.c \
+	eelf64briscv_fbsd.c \
 	eelf64ltsmip.c \
 	eelf64ltsmip_fbsd.c \
 	eelf64mmix.c \
@@ -1424,6 +1428,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_fbsd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Po@am__quote@
@@ -2419,6 +2424,7 @@  $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Pc@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx_linux.Pc@am__quote@
@@ -2584,9 +2590,11 @@  $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Pc@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Pc@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Pc@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Pc@am__quote@
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 0c780b24d57..e80264da132 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -742,8 +742,17 @@  riscv32be*-*-linux*)	targ_emul=elf32briscv
 			targ_extra_emuls="elf32briscv_ilp32f elf32briscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64"
 			targ_extra_libpath=$targ_extra_emuls
 			;;
+riscv32be*-*-freebsd*)	targ_emul=elf32briscv_fbsd
+			targ_extra_emuls="elf32lriscv elf32briscv elf64lriscv elf64briscv elf32lriscv_fbsd elf32briscv_fbsd elf64lriscv_fbsd elf64briscv_fbsd"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
 riscv32*-*-linux*)	targ_emul=elf32lriscv
 			targ_extra_emuls="elf32lriscv_ilp32f elf32lriscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64"
+			targ_extra_emuls="elf64lriscv elf32briscv elf64briscv"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
+riscv32*-*-freebsd*)	targ_emul=elf32lriscv_fbsd
+			targ_extra_emuls="elf32lriscv elf32briscv elf64lriscv elf64briscv elf32lriscv_fbsd elf32briscv_fbsd elf64lriscv_fbsd elf64briscv_fbsd"
 			targ_extra_libpath=$targ_extra_emuls
 			;;
 riscvbe-*-* | riscv32be*-*-*)
@@ -760,10 +769,18 @@  riscv64be*-*-linux*)	targ_emul=elf64briscv
 			targ_extra_emuls="elf64briscv_lp64f elf64briscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32"
 			targ_extra_libpath=$targ_extra_emuls
 			;;
+riscv64be*-*-freebsd*)	targ_emul=elf64briscv_fbsd
+			targ_extra_emuls="elf32lriscv elf32briscv elf64lriscv elf64briscv elf32lriscv_fbsd elf32briscv_fbsd elf64lriscv_fbsd elf64briscv_fbsd"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
 riscv64*-*-linux*)	targ_emul=elf64lriscv
 			targ_extra_emuls="elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32"
 			targ_extra_libpath=$targ_extra_emuls
 			;;
+riscv64*-*-freebsd*)	targ_emul=elf64lriscv_fbsd
+			targ_extra_emuls="elf32lriscv elf32briscv elf64lriscv elf64briscv elf32lriscv_fbsd elf32briscv_fbsd elf64lriscv_fbsd elf64briscv_fbsd"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
 riscv64be*-*-*)		targ_emul=elf64briscv
 			targ_extra_emuls="elf32briscv elf64lriscv elf32lriscv"
 			targ_extra_libpath=$targ_extra_emuls
diff --git a/ld/emulparams/elf32briscv_fbsd.sh b/ld/emulparams/elf32briscv_fbsd.sh
new file mode 100644
index 00000000000..c69559c68a1
--- /dev/null
+++ b/ld/emulparams/elf32briscv_fbsd.sh
@@ -0,0 +1,4 @@ 
+source_sh ${srcdir}/emulparams/elf32briscv.sh
+source_sh ${srcdir}/emulparams/elf_fbsd.sh
+
+OUTPUT_FORMAT="elf32-bigriscv-freebsd"
diff --git a/ld/emulparams/elf32lriscv_fbsd.sh b/ld/emulparams/elf32lriscv_fbsd.sh
new file mode 100644
index 00000000000..c97f149492b
--- /dev/null
+++ b/ld/emulparams/elf32lriscv_fbsd.sh
@@ -0,0 +1,4 @@ 
+source_sh ${srcdir}/emulparams/elf32lriscv.sh
+source_sh ${srcdir}/emulparams/elf_fbsd.sh
+
+OUTPUT_FORMAT="elf32-littleriscv-freebsd"
diff --git a/ld/emulparams/elf64briscv_fbsd.sh b/ld/emulparams/elf64briscv_fbsd.sh
new file mode 100644
index 00000000000..7cfdb3622eb
--- /dev/null
+++ b/ld/emulparams/elf64briscv_fbsd.sh
@@ -0,0 +1,4 @@ 
+source_sh ${srcdir}/emulparams/elf64briscv.sh
+source_sh ${srcdir}/emulparams/elf_fbsd.sh
+
+OUTPUT_FORMAT="elf64-bigriscv-freebsd"
diff --git a/ld/emulparams/elf64lriscv_fbsd.sh b/ld/emulparams/elf64lriscv_fbsd.sh
new file mode 100644
index 00000000000..4cdd9b6b44e
--- /dev/null
+++ b/ld/emulparams/elf64lriscv_fbsd.sh
@@ -0,0 +1,4 @@ 
+source_sh ${srcdir}/emulparams/elf64lriscv.sh
+source_sh ${srcdir}/emulparams/elf_fbsd.sh
+
+OUTPUT_FORMAT="elf64-littleriscv-freebsd"
diff --git a/ld/po/BLD-POTFILES.in b/ld/po/BLD-POTFILES.in
index 81d489f3f32..5a31df207c5 100644
--- a/ld/po/BLD-POTFILES.in
+++ b/ld/po/BLD-POTFILES.in
@@ -91,6 +91,7 @@  eelf32bmipn32.c
 eelf32briscv.c
 eelf32briscv_ilp32.c
 eelf32briscv_ilp32f.c
+eelf32briscv_fbsd.c
 eelf32bsmip.c
 eelf32btsmip.c
 eelf32btsmip_fbsd.c
@@ -124,6 +125,7 @@  eelf32lr5900n32.c
 eelf32lriscv.c
 eelf32lriscv_ilp32.c
 eelf32lriscv_ilp32f.c
+eelf32lriscv_fbsd.c
 eelf32lsmip.c
 eelf32ltsmip.c
 eelf32ltsmip_fbsd.c
@@ -179,6 +181,7 @@  eelf64bpf.c
 eelf64briscv.c
 eelf64briscv_lp64.c
 eelf64briscv_lp64f.c
+eelf64briscv_fbsd.c
 eelf64btsmip.c
 eelf64btsmip_fbsd.c
 eelf64hppa.c
@@ -187,6 +190,7 @@  eelf64lppc_fbsd.c
 eelf64lriscv.c
 eelf64lriscv_lp64.c
 eelf64lriscv_lp64f.c
+eelf64lriscv_fbsd.c
 eelf64ltsmip.c
 eelf64ltsmip_fbsd.c
 eelf64mmix.c