Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elfnn-riscv.c
index 20944c8109ffc7cb2553bdc4218703b4f8b8b6f3..eef1e800221ac25a2435b0370b8d03e4cc1d21dd 100644 (file)
@@ -1,5 +1,5 @@
 /* RISC-V-specific support for NN-bit ELF.
-   Copyright (C) 2011-2020 Free Software Foundation, Inc.
+   Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
    Contributed by Andrew Waterman (andrew@sifive.com).
    Based on TILE-Gx and MIPS targets.
 #include "elf/riscv.h"
 #include "opcode/riscv.h"
 #include "objalloc.h"
+#include "cpu-riscv.h"
+
+#include <limits.h>
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
 
 /* Internal relocations used exclusively by the relaxation pass.  */
 #define R_RISCV_DELETE (R_RISCV_max + 1)
@@ -62,16 +68,16 @@ struct riscv_elf_link_hash_entry
 {
   struct elf_link_hash_entry elf;
 
-#define GOT_UNKNOWN     0
-#define GOT_NORMAL      1
-#define GOT_TLS_GD      2
-#define GOT_TLS_IE      4
-#define GOT_TLS_LE      8
+#define GOT_UNKNOWN    0
+#define GOT_NORMAL     1
+#define GOT_TLS_GD     2
+#define GOT_TLS_IE     4
+#define GOT_TLS_LE     8
   char tls_type;
 };
 
 #define riscv_elf_hash_entry(ent) \
-  ((struct riscv_elf_link_hash_entry *)(ent))
+  ((struct riscv_elf_link_hash_entry *) (ent))
 
 struct _bfd_riscv_elf_obj_tdata
 {
@@ -96,7 +102,7 @@ struct _bfd_riscv_elf_obj_tdata
    && elf_tdata (bfd) != NULL                          \
    && elf_object_id (bfd) == RISCV_ELF_DATA)
 
-static bfd_boolean
+static bool
 elfNN_riscv_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd,
@@ -123,8 +129,26 @@ struct riscv_elf_link_hash_table
 
   /* The index of the last unused .rel.iplt slot.  */
   bfd_vma last_iplt_index;
+
+  /* Re-run the relaxations from relax pass 0 if TRUE.  */
+  bool restart_relax;
+
+  /* The data segment phase, don't relax the section
+     when it is exp_seg_relro_adjust.  */
+  int *data_segment_phase;
 };
 
+/* Instruction access functions. */
+#define riscv_get_insn(bits, ptr)              \
+  ((bits) == 16 ? bfd_getl16 (ptr)             \
+   : (bits) == 32 ? bfd_getl32 (ptr)           \
+   : (bits) == 64 ? bfd_getl64 (ptr)           \
+   : (abort (), (bfd_vma) - 1))
+#define riscv_put_insn(bits, val, ptr)         \
+  ((bits) == 16 ? bfd_putl16 (val, ptr)                \
+   : (bits) == 32 ? bfd_putl32 (val, ptr)      \
+   : (bits) == 64 ? bfd_putl64 (val, ptr)      \
+   : (abort (), (void) 0))
 
 /* Get the RISC-V ELF linker hash table from a link_info structure.  */
 #define riscv_elf_hash_table(p) \
@@ -132,7 +156,7 @@ struct riscv_elf_link_hash_table
     && elf_hash_table_id (elf_hash_table (p)) == RISCV_ELF_DATA)       \
    ? (struct riscv_elf_link_hash_table *) (p)->hash : NULL)
 
-static bfd_boolean
+static bool
 riscv_info_to_howto_rela (bfd *abfd,
                          arelent *cache_ptr,
                          Elf_Internal_Rela *dst)
@@ -152,15 +176,25 @@ riscv_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   bed->s->swap_reloca_out (abfd, rel, loc);
 }
 
-/* PLT/GOT stuff.  */
+/* Return true if a relocation is modifying an instruction. */
+
+static bool
+riscv_is_insn_reloc (const reloc_howto_type *howto)
+{
+  /* Heuristic: A multibyte destination with a nontrivial mask
+     is an instruction */
+  return (howto->bitsize > 8
+         && howto->dst_mask != 0
+         && ~(howto->dst_mask | (howto->bitsize < sizeof(bfd_vma) * CHAR_BIT
+              ? (MINUS_ONE << howto->bitsize) : (bfd_vma)0)) != 0);
+}
 
+/* PLT/GOT stuff.  */
 #define PLT_HEADER_INSNS 8
 #define PLT_ENTRY_INSNS 4
 #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
 #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
-
 #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?  */
@@ -176,7 +210,7 @@ riscv_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
 
 /* Generate a PLT header.  */
 
-static bfd_boolean
+static bool
 riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
                       uint32_t *entry)
 {
@@ -188,7 +222,7 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
     {
       _bfd_error_handler (_("%pB: warning: RVE PLT generation not supported"),
                          output_bfd);
-      return FALSE;
+      return false;
     }
 
   /* auipc  t2, %hi(.got.plt)
@@ -198,7 +232,7 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
      addi   t0, t2, %lo(.got.plt)    # &.got.plt
      srli   t1, t1, log2(16/PTRSIZE) # .got.plt offset
      l[w|d] t0, PTRSIZE(t0)         # link map
-     jr            t3 */
+     jr            t3  */
 
   entry[0] = RISCV_UTYPE (AUIPC, X_T2, gotplt_offset_high);
   entry[1] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T3);
@@ -209,12 +243,12 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
   entry[6] = RISCV_ITYPE (LREG, X_T0, X_T0, RISCV_ELF_WORD_BYTES);
   entry[7] = RISCV_ITYPE (JALR, 0, X_T3, 0);
 
-  return TRUE;
+  return true;
 }
 
 /* Generate a PLT entry.  */
 
-static bfd_boolean
+static bool
 riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr,
                      uint32_t *entry)
 {
@@ -223,20 +257,20 @@ riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr,
     {
       _bfd_error_handler (_("%pB: warning: RVE PLT generation not supported"),
                          output_bfd);
-      return FALSE;
+      return false;
     }
 
   /* auipc  t3, %hi(.got.plt entry)
      l[w|d] t3, %lo(.got.plt entry)(t3)
      jalr   t1, t3
-     nop */
+     nop  */
 
   entry[0] = RISCV_UTYPE (AUIPC, X_T3, RISCV_PCREL_HIGH_PART (got, addr));
   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;
+  return true;
 }
 
 /* Create an entry in an RISC-V ELF linker hash table.  */
@@ -270,9 +304,9 @@ link_hash_newfunc (struct bfd_hash_entry *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.  */
+   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)
@@ -297,7 +331,7 @@ riscv_elf_local_htab_eq (const void *ptr1, const void *ptr2)
 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)
+                             bool create)
 {
   struct riscv_elf_link_hash_entry eh, *ret;
   asection *sec = abfd->sections;
@@ -370,6 +404,7 @@ riscv_elf_link_hash_table_create (bfd *abfd)
     }
 
   ret->max_alignment = (bfd_vma) -1;
+  ret->restart_relax = false;
 
   /* Create hash table for local ifunc.  */
   ret->loc_hash_table = htab_try_create (1024,
@@ -389,7 +424,7 @@ riscv_elf_link_hash_table_create (bfd *abfd)
 
 /* Create the .got section.  */
 
-static bfd_boolean
+static bool
 riscv_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
@@ -400,7 +435,7 @@ riscv_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 
   /* This function may be called more than once.  */
   if (htab->sgot != NULL)
-    return TRUE;
+    return true;
 
   flags = bed->dynamic_sec_flags;
 
@@ -411,13 +446,13 @@ riscv_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                           | SEC_READONLY));
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
   htab->srelgot = s;
 
   s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
   htab->sgot = s;
 
   /* The first bit of the global offset table is the header.  */
@@ -428,7 +463,7 @@ riscv_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
       s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
          || !bfd_set_section_alignment (s, bed->s->log_file_align))
-       return FALSE;
+       return false;
       htab->sgotplt = s;
 
       /* Reserve room for the header.  */
@@ -445,17 +480,17 @@ riscv_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                       "_GLOBAL_OFFSET_TABLE_");
       elf_hash_table (info)->hgot = h;
       if (h == NULL)
-       return FALSE;
+       return false;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
    .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
    hash table.  */
 
-static bfd_boolean
+static bool
 riscv_elf_create_dynamic_sections (bfd *dynobj,
                                   struct bfd_link_info *info)
 {
@@ -465,10 +500,10 @@ riscv_elf_create_dynamic_sections (bfd *dynobj,
   BFD_ASSERT (htab != NULL);
 
   if (!riscv_elf_create_got_section (dynobj, info))
-    return FALSE;
+    return false;
 
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
-    return FALSE;
+    return false;
 
   if (!bfd_link_pic (info))
     {
@@ -496,7 +531,7 @@ riscv_elf_create_dynamic_sections (bfd *dynobj,
       || (!bfd_link_pic (info) && (!htab->elf.srelbss || !htab->sdyntdata)))
     abort ();
 
-  return TRUE;
+  return true;
 }
 
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
@@ -520,7 +555,7 @@ riscv_elf_copy_indirect_symbol (struct bfd_link_info *info,
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
-static bfd_boolean
+static bool
 riscv_elf_record_tls_type (bfd *abfd, struct elf_link_hash_entry *h,
                           unsigned long symndx, char tls_type)
 {
@@ -532,12 +567,12 @@ riscv_elf_record_tls_type (bfd *abfd, struct elf_link_hash_entry *h,
       (*_bfd_error_handler)
        (_("%pB: `%s' accessed both as normal and thread local symbol"),
         abfd, h ? h->root.root.string : "<local>");
-      return FALSE;
+      return false;
     }
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 riscv_elf_record_got_reference (bfd *abfd, struct bfd_link_info *info,
                                struct elf_link_hash_entry *h, long symndx)
 {
@@ -547,13 +582,13 @@ riscv_elf_record_got_reference (bfd *abfd, struct bfd_link_info *info,
   if (htab->elf.sgot == NULL)
     {
       if (!riscv_elf_create_got_section (htab->elf.dynobj, info))
-       return FALSE;
+       return false;
     }
 
   if (h != NULL)
     {
       h->got.refcount += 1;
-      return TRUE;
+      return true;
     }
 
   /* This is a global offset table entry for a local symbol.  */
@@ -561,16 +596,16 @@ riscv_elf_record_got_reference (bfd *abfd, struct bfd_link_info *info,
     {
       bfd_size_type size = symtab_hdr->sh_info * (sizeof (bfd_vma) + 1);
       if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
-       return FALSE;
+       return false;
       _bfd_riscv_elf_local_got_tls_type (abfd)
        = (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
     }
   elf_local_got_refcounts (abfd) [symndx] += 1;
 
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 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);
@@ -584,13 +619,14 @@ bad_static_reloc (bfd *abfd, unsigned r_type, struct elf_link_hash_entry *h)
      abfd, r ? r->name : _("<unknown>"),
      h != NULL ? h->root.root.string : "a local symbol");
   bfd_set_error (bfd_error_bad_value);
-  return FALSE;
+  return false;
 }
+
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table or procedure linkage
    table.  */
 
-static bfd_boolean
+static bool
 riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                        asection *sec, const Elf_Internal_Rela *relocs)
 {
@@ -601,7 +637,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   asection *sreloc = NULL;
 
   if (bfd_link_relocatable (info))
-    return TRUE;
+    return true;
 
   htab = riscv_elf_hash_table (info);
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -623,7 +659,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        {
          (*_bfd_error_handler) (_("%pB: bad symbol index: %d"),
                                 abfd, r_symndx);
-         return FALSE;
+         return false;
        }
 
       if (r_symndx < symtab_hdr->sh_info)
@@ -632,14 +668,14 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                                          abfd, r_symndx);
          if (isym == NULL)
-           return FALSE;
+           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);
+             h = riscv_elf_get_local_sym_hash (htab, abfd, rel, true);
              if (h == NULL)
-               return FALSE;
+               return false;
 
              /* Fake STT_GNU_IFUNC global symbol.  */
              h->root.root.string = bfd_elf_sym_name (abfd, symtab_hdr,
@@ -676,7 +712,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                 executables.  */
              if (h->type == STT_GNU_IFUNC
                  && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
-               return FALSE;
+               return false;
              break;
 
            default:
@@ -692,7 +728,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_RISCV_TLS_GD_HI20:
          if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
              || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_GD))
-           return FALSE;
+           return false;
          break;
 
        case R_RISCV_TLS_GOT_HI20:
@@ -700,19 +736,19 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            info->flags |= DF_STATIC_TLS;
          if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
              || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_IE))
-           return FALSE;
+           return false;
          break;
 
        case R_RISCV_GOT_HI20:
          if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
              || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_NORMAL))
-           return FALSE;
+           return false;
          break;
 
        case R_RISCV_CALL:
        case R_RISCV_CALL_PLT:
-         /* These symbol requires a procedure linkage table entry.  We
-            actually build the entry in adjust_dynamic_symbol,
+         /* These symbol requires a procedure linkage table entry.
+            We actually build the entry in adjust_dynamic_symbol,
             because these might be a case of linking PIC code without
             linking in any dynamic objects, in which case we don't
             need to generate a procedure linkage table after all.  */
@@ -842,10 +878,10 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                {
                  sreloc = _bfd_elf_make_dynamic_reloc_section
                    (sec, htab->elf.dynobj, RISCV_ELF_LOG_WORD_BYTES,
-                   abfd, /*rela?*/ TRUE);
+                   abfd, /*rela?*/ true);
 
                  if (sreloc == NULL)
-                   return FALSE;
+                   return false;
                }
 
              /* If this is a global symbol, we count the number of
@@ -865,7 +901,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                                abfd, r_symndx);
                  if (isym == NULL)
-                   return FALSE;
+                   return false;
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s == NULL)
@@ -882,7 +918,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
                  if (p == NULL)
-                   return FALSE;
+                   return false;
                  p->next = *head;
                  *head = p;
                  p->sec = sec;
@@ -898,12 +934,12 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_RISCV_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-           return FALSE;
+           return false;
          break;
 
        case R_RISCV_GNU_VTENTRY:
          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-           return FALSE;
+           return false;
          break;
 
        default:
@@ -911,7 +947,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 static asection *
@@ -938,7 +974,7 @@ riscv_elf_gc_mark_hook (asection *sec,
    change the definition to something the rest of the link can
    understand.  */
 
-static bfd_boolean
+static bool
 riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
                                 struct elf_link_hash_entry *h)
 {
@@ -980,7 +1016,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          h->needs_plt = 0;
        }
 
-      return TRUE;
+      return true;
     }
   else
     h->plt.offset = (bfd_vma) -1;
@@ -994,7 +1030,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       BFD_ASSERT (def->root.type == bfd_link_hash_defined);
       h->root.u.def.section = def->root.u.def.section;
       h->root.u.def.value = def->root.u.def.value;
-      return TRUE;
+      return true;
     }
 
   /* This is a reference to a symbol defined by a dynamic object which
@@ -1005,18 +1041,18 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
   if (bfd_link_pic (info))
-    return TRUE;
+    return true;
 
   /* If there are no references to this symbol that do not use the
      GOT, we don't need to generate a copy reloc.  */
   if (!h->non_got_ref)
-    return TRUE;
+    return true;
 
   /* If -z nocopyreloc was given, we won't generate them either.  */
   if (info->nocopyreloc)
     {
       h->non_got_ref = 0;
-      return TRUE;
+      return true;
     }
 
   /* If we don't find any dynamic relocs in read-only sections, then
@@ -1024,7 +1060,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (!_bfd_elf_readonly_dynrelocs (h))
     {
       h->non_got_ref = 0;
-      return TRUE;
+      return true;
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -1069,7 +1105,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 /* Allocate space in .plt, .got and associated reloc sections for
    dynamic relocs.  */
 
-static bfd_boolean
+static bool
 allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info;
@@ -1077,18 +1113,27 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   struct elf_dyn_relocs *p;
 
   if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
+    return true;
 
   info = (struct bfd_link_info *) inf;
   htab = riscv_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
 
+  /* When we are generating pde, make sure gp symbol is output as a
+     dynamic symbol.  Then ld.so can set the gp register earlier, before
+     resolving the ifunc.  */
+  if (!bfd_link_pic (info)
+      && htab->elf.dynamic_sections_created
+      && strcmp (h->root.root.string, RISCV_GP_SYMBOL) == 0
+      && !bfd_elf_link_record_dynamic_symbol (info, h))
+    return false;
+
   /* 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;
+    return true;
   else if (htab->elf.dynamic_sections_created
           && h->plt.refcount > 0)
     {
@@ -1098,7 +1143,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
+           return false;
        }
 
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
@@ -1146,7 +1191,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   if (h->got.refcount > 0)
     {
       asection *s;
-      bfd_boolean dyn;
+      bool dyn;
       int tls_type = riscv_elf_hash_entry (h)->tls_type;
 
       /* Make sure this symbol is output as a dynamic symbol.
@@ -1155,7 +1200,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
+           return false;
        }
 
       s = htab->elf.sgot;
@@ -1189,7 +1234,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
     h->got.offset = (bfd_vma) -1;
 
   if (h->dyn_relocs == NULL)
-    return TRUE;
+    return true;
 
   /* In the shared -Bsymbolic case, discard space allocated for
      dynamic pc-relative relocs against symbols which turn out to be
@@ -1229,7 +1274,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                   && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
            }
        }
     }
@@ -1252,7 +1297,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
              && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
            }
 
          /* If that succeeded, we know we'll be keeping all the
@@ -1273,20 +1318,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       sreloc->size += p->count * sizeof (ElfNN_External_Rela);
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
    ifunc dynamic relocs.  */
 
-static bfd_boolean
+static bool
 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;
+    return true;
 
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -1302,14 +1347,14 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
                                               PLT_ENTRY_SIZE,
                                               PLT_HEADER_SIZE,
                                               GOT_ENTRY_SIZE,
-                                              TRUE);
-  return TRUE;
+                                              true);
+  return true;
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
    local ifunc dynamic relocs.  */
 
-static bfd_boolean
+static int
 allocate_local_ifunc_dynrelocs (void **slot, void *inf)
 {
   struct elf_link_hash_entry *h
@@ -1325,7 +1370,7 @@ allocate_local_ifunc_dynrelocs (void **slot, void *inf)
   return allocate_ifunc_dynrelocs (h, inf);
 }
 
-static bfd_boolean
+static bool
 riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 {
   struct riscv_elf_link_hash_table *htab;
@@ -1437,7 +1482,7 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
       struct elf_link_hash_entry *got;
       got = elf_link_hash_lookup (elf_hash_table (info),
                                  "_GLOBAL_OFFSET_TABLE_",
-                                 FALSE, FALSE, FALSE);
+                                 false, false, false);
 
       /* Don't allocate .got.plt section if there are no GOT nor PLT
         entries and there is no refeence to _GLOBAL_OFFSET_TABLE_.  */
@@ -1472,7 +1517,7 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if (strncmp (s->name, ".rela", 5) == 0)
+      else if (startswith (s->name, ".rela"))
        {
          if (s->size != 0)
            {
@@ -1510,10 +1555,10 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
         at the beginning, and we don't want garbage.  */
       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
-       return FALSE;
+       return false;
     }
 
-  return _bfd_elf_add_dynamic_tags (output_bfd, info, TRUE);
+  return _bfd_elf_add_dynamic_tags (output_bfd, info, true);
 }
 
 #define TP_OFFSET 0
@@ -1548,7 +1593,7 @@ riscv_global_pointer_value (struct bfd_link_info *info)
 {
   struct bfd_link_hash_entry *h;
 
-  h = bfd_link_hash_lookup (info->hash, RISCV_GP_SYMBOL, FALSE, FALSE, TRUE);
+  h = bfd_link_hash_lookup (info->hash, RISCV_GP_SYMBOL, false, false, true);
   if (h == NULL || h->type != bfd_link_hash_defined)
     return 0;
 
@@ -1607,27 +1652,27 @@ perform_relocation (const reloc_howto_type *howto,
       break;
 
     case R_RISCV_JAL:
-      if (!VALID_UJTYPE_IMM (value))
+      if (!VALID_JTYPE_IMM (value))
        return bfd_reloc_overflow;
-      value = ENCODE_UJTYPE_IMM (value);
+      value = ENCODE_JTYPE_IMM (value);
       break;
 
     case R_RISCV_BRANCH:
-      if (!VALID_SBTYPE_IMM (value))
+      if (!VALID_BTYPE_IMM (value))
        return bfd_reloc_overflow;
-      value = ENCODE_SBTYPE_IMM (value);
+      value = ENCODE_BTYPE_IMM (value);
       break;
 
     case R_RISCV_RVC_BRANCH:
-      if (!VALID_RVC_B_IMM (value))
+      if (!VALID_CBTYPE_IMM (value))
        return bfd_reloc_overflow;
-      value = ENCODE_RVC_B_IMM (value);
+      value = ENCODE_CBTYPE_IMM (value);
       break;
 
     case R_RISCV_RVC_JUMP:
-      if (!VALID_RVC_J_IMM (value))
+      if (!VALID_CJTYPE_IMM (value))
        return bfd_reloc_overflow;
-      value = ENCODE_RVC_J_IMM (value);
+      value = ENCODE_CJTYPE_IMM (value);
       break;
 
     case R_RISCV_RVC_LUI:
@@ -1636,16 +1681,16 @@ perform_relocation (const reloc_howto_type *howto,
          /* Linker relaxation can convert an address equal to or greater than
             0x800 to slightly below 0x800.  C.LUI does not accept zero as a
             valid immediate.  We can fix this by converting it to a C.LI.  */
-         bfd_vma insn = bfd_get (howto->bitsize, input_bfd,
-                                 contents + rel->r_offset);
+         bfd_vma insn = riscv_get_insn (howto->bitsize,
+                                        contents + rel->r_offset);
          insn = (insn & ~MATCH_C_LUI) | MATCH_C_LI;
-         bfd_put (howto->bitsize, input_bfd, insn, contents + rel->r_offset);
-         value = ENCODE_RVC_IMM (0);
+         riscv_put_insn (howto->bitsize, insn, contents + rel->r_offset);
+         value = ENCODE_CITYPE_IMM (0);
        }
-      else if (!VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value)))
+      else if (!VALID_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (value)))
        return bfd_reloc_overflow;
       else
-       value = ENCODE_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value));
+       value = ENCODE_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (value));
       break;
 
     case R_RISCV_32:
@@ -1675,9 +1720,16 @@ perform_relocation (const reloc_howto_type *howto,
       return bfd_reloc_notsupported;
     }
 
-  bfd_vma word = bfd_get (howto->bitsize, input_bfd, contents + rel->r_offset);
+  bfd_vma word;
+  if (riscv_is_insn_reloc (howto))
+    word = riscv_get_insn (howto->bitsize, contents + rel->r_offset);
+  else
+    word = bfd_get (howto->bitsize, input_bfd, contents + rel->r_offset);
   word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
-  bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
+  if (riscv_is_insn_reloc (howto))
+    riscv_put_insn (howto->bitsize, word, contents + rel->r_offset);
+  else
+    bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
 
   return bfd_reloc_ok;
 }
@@ -1693,14 +1745,14 @@ typedef struct
 
 typedef struct riscv_pcrel_lo_reloc
 {
-  asection *                    input_section;
-  struct bfd_link_info *        info;
-  reloc_howto_type *            howto;
-  const Elf_Internal_Rela *     reloc;
-  bfd_vma                       addr;
-  const char *                  name;
-  bfd_byte *                    contents;
-  struct riscv_pcrel_lo_reloc *         next;
+  asection *input_section;
+  struct bfd_link_info *info;
+  reloc_howto_type *howto;
+  const Elf_Internal_Rela *reloc;
+  bfd_vma addr;
+  const char *name;
+  bfd_byte *contents;
+  struct riscv_pcrel_lo_reloc *next;
 } riscv_pcrel_lo_reloc;
 
 typedef struct
@@ -1716,17 +1768,16 @@ riscv_pcrel_reloc_hash (const void *entry)
   return (hashval_t)(e->address >> 2);
 }
 
-static bfd_boolean
+static int
 riscv_pcrel_reloc_eq (const void *entry1, const void *entry2)
 {
   const riscv_pcrel_hi_reloc *e1 = entry1, *e2 = entry2;
   return e1->address == e2->address;
 }
 
-static bfd_boolean
+static bool
 riscv_init_pcrel_relocs (riscv_pcrel_relocs *p)
 {
-
   p->lo_relocs = NULL;
   p->hi_relocs = htab_create (1024, riscv_pcrel_reloc_hash,
                              riscv_pcrel_reloc_eq, free);
@@ -1748,48 +1799,48 @@ riscv_free_pcrel_relocs (riscv_pcrel_relocs *p)
   htab_delete (p->hi_relocs);
 }
 
-static bfd_boolean
+static bool
 riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel,
                           struct bfd_link_info *info,
                           bfd_vma pc,
                           bfd_vma addr,
                           bfd_byte *contents,
                           const reloc_howto_type *howto,
-                          bfd *input_bfd)
+                          bfd *input_bfd ATTRIBUTE_UNUSED)
 {
   /* We may need to reference low addreses in PC-relative modes even when the
-   * PC is far away from these addresses.  For example, undefweak references
-   * need to produce the address 0 when linked.  As 0 is far from the arbitrary
-   * addresses that we can link PC-relative programs at, the linker can't
-   * actually relocate references to those symbols.  In order to allow these
-   * programs to work we simply convert the PC-relative auipc sequences to
-   * 0-relative lui sequences.  */
+     PC is far away from these addresses.  For example, undefweak references
+     need to produce the address 0 when linked.  As 0 is far from the arbitrary
+     addresses that we can link PC-relative programs at, the linker can't
+     actually relocate references to those symbols.  In order to allow these
+     programs to work we simply convert the PC-relative auipc sequences to
+     0-relative lui sequences.  */
   if (bfd_link_pic (info))
-    return FALSE;
+    return false;
 
   /* If it's possible to reference the symbol using auipc we do so, as that's
-   * more in the spirit of the PC-relative relocations we're processing.  */
+     more in the spirit of the PC-relative relocations we're processing.  */
   bfd_vma offset = addr - pc;
   if (ARCH_SIZE == 32 || VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (offset)))
-    return FALSE;
+    return false;
 
   /* If it's impossible to reference this with a LUI-based offset then don't
-   * bother to convert it at all so users still see the PC-relative relocation
-   * in the truncation message.  */
+     bother to convert it at all so users still see the PC-relative relocation
+     in the truncation message.  */
   if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (addr)))
-    return FALSE;
+    return false;
 
-  rel->r_info = ELFNN_R_INFO(addr, R_RISCV_HI20);
+  rel->r_info = ELFNN_R_INFO (addr, R_RISCV_HI20);
 
-  bfd_vma insn = bfd_get(howto->bitsize, input_bfd, contents + rel->r_offset);
+  bfd_vma insn = riscv_get_insn (howto->bitsize, contents + rel->r_offset);
   insn = (insn & ~MASK_AUIPC) | MATCH_LUI;
-  bfd_put(howto->bitsize, input_bfd, insn, contents + rel->r_offset);
-  return TRUE;
+  riscv_put_insn (howto->bitsize, insn, contents + rel->r_offset);
+  return true;
 }
 
-static bfd_boolean
+static bool
 riscv_record_pcrel_hi_reloc (riscv_pcrel_relocs *p, bfd_vma addr,
-                            bfd_vma value, bfd_boolean absolute)
+                            bfd_vma value, bool absolute)
 {
   bfd_vma offset = absolute ? value : value - addr;
   riscv_pcrel_hi_reloc entry = {addr, offset};
@@ -1799,12 +1850,12 @@ riscv_record_pcrel_hi_reloc (riscv_pcrel_relocs *p, bfd_vma addr,
   BFD_ASSERT (*slot == NULL);
   *slot = (riscv_pcrel_hi_reloc *) bfd_malloc (sizeof (riscv_pcrel_hi_reloc));
   if (*slot == NULL)
-    return FALSE;
+    return false;
   **slot = entry;
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 riscv_record_pcrel_lo_reloc (riscv_pcrel_relocs *p,
                             asection *input_section,
                             struct bfd_link_info *info,
@@ -1817,14 +1868,14 @@ riscv_record_pcrel_lo_reloc (riscv_pcrel_relocs *p,
   riscv_pcrel_lo_reloc *entry;
   entry = (riscv_pcrel_lo_reloc *) bfd_malloc (sizeof (riscv_pcrel_lo_reloc));
   if (entry == NULL)
-    return FALSE;
+    return false;
   *entry = (riscv_pcrel_lo_reloc) {input_section, info, howto, reloc, addr,
                                   name, contents, p->lo_relocs};
   p->lo_relocs = entry;
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p)
 {
   riscv_pcrel_lo_reloc *r;
@@ -1836,23 +1887,33 @@ riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p)
       riscv_pcrel_hi_reloc search = {r->addr, 0};
       riscv_pcrel_hi_reloc *entry = htab_find (p->hi_relocs, &search);
       if (entry == NULL
-         /* Check for overflow into bit 11 when adding reloc addend.  */
-         || (! (entry->value & 0x800)
-             && ((entry->value + r->reloc->r_addend) & 0x800)))
+         /* Check the overflow when adding reloc addend.  */
+         || (RISCV_CONST_HIGH_PART (entry->value)
+             != RISCV_CONST_HIGH_PART (entry->value + r->reloc->r_addend)))
        {
-         char *string = (entry == NULL
-                         ? "%pcrel_lo missing matching %pcrel_hi"
-                         : "%pcrel_lo overflow with an addend");
+         char *string;
+         if (entry == NULL)
+           string = _("%pcrel_lo missing matching %pcrel_hi");
+         else if (asprintf (&string,
+                            _("%%pcrel_lo overflow with an addend, the "
+                              "value of %%pcrel_hi is 0x%" PRIx64 " without "
+                              "any addend, but may be 0x%" PRIx64 " after "
+                              "adding the %%pcrel_lo addend"),
+                            (int64_t) RISCV_CONST_HIGH_PART (entry->value),
+                            (int64_t) RISCV_CONST_HIGH_PART
+                               (entry->value + r->reloc->r_addend)) == -1)
+           string = _("%pcrel_lo overflow with an addend");
+
          (*r->info->callbacks->reloc_dangerous)
            (r->info, string, input_bfd, r->input_section, r->reloc->r_offset);
-         return TRUE;
+         return true;
        }
 
       perform_relocation (r->howto, r->reloc, entry->value, r->input_section,
                          input_bfd, r->contents);
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Relocate a RISC-V ELF section.
@@ -1883,7 +1944,7 @@ riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p)
    section, which means that the addend must be adjusted
    accordingly.  */
 
-static bfd_boolean
+static int
 riscv_elf_relocate_section (bfd *output_bfd,
                            struct bfd_link_info *info,
                            bfd *input_bfd,
@@ -1896,15 +1957,15 @@ riscv_elf_relocate_section (bfd *output_bfd,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
   riscv_pcrel_relocs pcrel_relocs;
-  bfd_boolean ret = FALSE;
+  bool ret = false;
   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);
   bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
-  bfd_boolean absolute;
+  bool absolute;
 
   if (!riscv_init_pcrel_relocs (&pcrel_relocs))
-    return FALSE;
+    return false;
 
   relend = relocs + input_section->reloc_count;
   for (rel = relocs; rel < relend; rel++)
@@ -1917,13 +1978,13 @@ riscv_elf_relocate_section (bfd *output_bfd,
       bfd_reloc_status_type r = bfd_reloc_ok;
       const char *name = NULL;
       bfd_vma off, ie_off;
-      bfd_boolean unresolved_reloc, is_ie = FALSE;
+      bool unresolved_reloc, is_ie = false;
       bfd_vma pc = sec_addr (input_section) + rel->r_offset;
       int r_type = ELFNN_R_TYPE (rel->r_info), tls_type;
       reloc_howto_type *howto = riscv_elf_rtype_to_howto (input_bfd, r_type);
       const char *msg = NULL;
       char *msg_buf = NULL;
-      bfd_boolean resolved_to_zero;
+      bool resolved_to_zero;
 
       if (howto == NULL
          || r_type == R_RISCV_GNU_VTINHERIT || r_type == R_RISCV_GNU_VTENTRY)
@@ -1934,7 +1995,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
       h = NULL;
       sym = NULL;
       sec = NULL;
-      unresolved_reloc = FALSE;
+      unresolved_reloc = false;
       if (r_symndx < symtab_hdr->sh_info)
        {
          sym = local_syms + r_symndx;
@@ -1945,7 +2006,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
          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);
+             h = riscv_elf_get_local_sym_hash (htab, input_bfd, rel, false);
              if (h == NULL)
                abort ();
 
@@ -1956,7 +2017,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
        }
       else
        {
-         bfd_boolean warned, ignored;
+         bool warned, ignored;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
@@ -2039,7 +2100,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                       "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;
+                 return false;
                }
 
                /* Generate dynamic relocation only when there is a non-GOT
@@ -2169,7 +2230,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                if (howto == NULL)
                  r = bfd_reloc_notsupported;
                else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
-                                                      relocation, FALSE))
+                                                      relocation, false))
                  r = bfd_reloc_overflow;
                goto do_relocation;
 
@@ -2186,12 +2247,12 @@ riscv_elf_relocate_section (bfd *output_bfd,
                if (howto == NULL)
                  r = bfd_reloc_notsupported;
                else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
-                                                      relocation, FALSE))
+                                                      relocation, false))
                  r = bfd_reloc_overflow;
                goto do_relocation;
 
            default:
- bad_ifunc_reloc:
          bad_ifunc_reloc:
              if (h->root.root.string)
                name = h->root.root.string;
              else
@@ -2205,11 +2266,11 @@ riscv_elf_relocate_section (bfd *output_bfd,
                 "symbol `%s' isn't supported"), input_bfd,
               howto->name, name);
              bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+             return false;
            }
        }
 
- skip_ifunc:
   skip_ifunc:
       if (h != NULL)
        name = h->root.root.string;
       else
@@ -2252,7 +2313,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
        case R_RISCV_GOT_HI20:
          if (h != NULL)
            {
-             bfd_boolean dyn, pic;
+             bool dyn, pic;
 
              off = h->got.offset;
              BFD_ASSERT (off != (bfd_vma) -1);
@@ -2284,7 +2345,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                    }
                }
              else
-               unresolved_reloc = FALSE;
+               unresolved_reloc = false;
            }
          else
            {
@@ -2371,10 +2432,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
              && (!bfd_link_pic (info) || h->plt.offset == MINUS_ONE))
            {
              /* We can use x0 as the base register.  */
-             bfd_vma insn = bfd_get_32 (input_bfd,
-                                        contents + rel->r_offset + 4);
+             bfd_vma insn = bfd_getl32 (contents + rel->r_offset + 4);
              insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
-             bfd_put_32 (input_bfd, insn, contents + rel->r_offset + 4);
+             bfd_putl32 (insn, contents + rel->r_offset + 4);
              /* Set the relocation value so that we get 0 after the pc
                 relative adjustment.  */
              relocation = sec_addr (input_section) + rel->r_offset;
@@ -2388,7 +2448,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
            {
              /* Refer to the PLT entry.  */
              relocation = sec_addr (htab->elf.splt) + h->plt.offset;
-             unresolved_reloc = FALSE;
+             unresolved_reloc = false;
            }
          break;
 
@@ -2407,10 +2467,10 @@ riscv_elf_relocate_section (bfd *output_bfd,
          if (VALID_ITYPE_IMM (relocation + rel->r_addend))
            {
              /* We can use tp as the base register.  */
-             bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+             bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
              insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
              insn |= X_TP << OP_SH_RS1;
-             bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+             bfd_putl32 (insn, contents + rel->r_offset);
            }
          else
            r = bfd_reloc_overflow;
@@ -2420,18 +2480,18 @@ riscv_elf_relocate_section (bfd *output_bfd,
        case R_RISCV_GPREL_S:
          {
            bfd_vma gp = riscv_global_pointer_value (info);
-           bfd_boolean x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend);
+           bool x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend);
            if (x0_base || VALID_ITYPE_IMM (relocation + rel->r_addend - gp))
              {
                /* We can use x0 or gp as the base register.  */
-               bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+               bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
                insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
                if (!x0_base)
                  {
                    rel->r_addend -= gp;
                    insn |= X_GP << OP_SH_RS1;
                  }
-               bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+               bfd_putl32 (insn, contents + rel->r_offset);
              }
            else
              r = bfd_reloc_overflow;
@@ -2494,7 +2554,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                   || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                       && !resolved_to_zero)
                   || h->root.type != bfd_link_hash_undefweak)
-              && (! howto->pc_relative
+              && (!howto->pc_relative
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (!bfd_link_pic (info)
                  && h != NULL
@@ -2507,7 +2567,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
            {
              Elf_Internal_Rela outrel;
              asection *sreloc;
-             bfd_boolean skip_static_relocation, skip_dynamic_relocation;
+             bool skip_static_relocation, skip_dynamic_relocation;
 
              /* When generating a shared object, these relocations
                 are copied into the output file to be resolved at run
@@ -2544,7 +2604,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_RISCV_TLS_GOT_HI20:
-         is_ie = TRUE;
+         is_ie = true;
          /* Fall through.  */
 
        case R_RISCV_TLS_GD_HI20:
@@ -2573,14 +2633,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
            {
              Elf_Internal_Rela outrel;
              int indx = 0;
-             bfd_boolean need_relocs = FALSE;
+             bool need_relocs = false;
 
              if (htab->elf.srelgot == NULL)
                abort ();
 
              if (h != NULL)
                {
-                 bfd_boolean dyn, pic;
+                 bool dyn, pic;
                  dyn = htab->elf.dynamic_sections_created;
                  pic = bfd_link_pic (info);
 
@@ -2595,7 +2655,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                  && (h == NULL
                      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                      || h->root.type != bfd_link_hash_undefweak))
-                   need_relocs = TRUE;
+                   need_relocs = true;
 
              if (tls_type & GOT_TLS_GD)
                {
@@ -2612,14 +2672,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
                          BFD_ASSERT (! unresolved_reloc);
                          bfd_put_NN (output_bfd,
                                      dtpoff (info, relocation),
-                                     (htab->elf.sgot->contents + off +
-                                      RISCV_ELF_WORD_BYTES));
+                                     (htab->elf.sgot->contents
+                                      + off + RISCV_ELF_WORD_BYTES));
                        }
                      else
                        {
                          bfd_put_NN (output_bfd, 0,
-                                     (htab->elf.sgot->contents + off +
-                                      RISCV_ELF_WORD_BYTES));
+                                     (htab->elf.sgot->contents
+                                      + off + RISCV_ELF_WORD_BYTES));
                          outrel.r_info = ELFNN_R_INFO (indx, R_RISCV_TLS_DTPRELNN);
                          outrel.r_offset += RISCV_ELF_WORD_BYTES;
                          riscv_elf_append_rela (output_bfd, htab->elf.srelgot, &outrel);
@@ -2636,8 +2696,8 @@ riscv_elf_relocate_section (bfd *output_bfd,
                                  htab->elf.sgot->contents + off);
                      bfd_put_NN (output_bfd,
                                  dtpoff (info, relocation),
-                                 (htab->elf.sgot->contents + off +
-                                  RISCV_ELF_WORD_BYTES));
+                                 (htab->elf.sgot->contents
+                                  + off + RISCV_ELF_WORD_BYTES));
                   }
                }
 
@@ -2648,7 +2708,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                      bfd_put_NN (output_bfd, 0,
                                  htab->elf.sgot->contents + off + ie_off);
                      outrel.r_offset = sec_addr (htab->elf.sgot)
-                                      + off + ie_off;
+                                       + off + ie_off;
                      outrel.r_addend = 0;
                      if (indx == 0)
                        outrel.r_addend = tpoff (info, relocation);
@@ -2666,9 +2726,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
          BFD_ASSERT (off < (bfd_vma) -2);
          relocation = sec_addr (htab->elf.sgot) + off + (is_ie ? ie_off : 0);
          if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
-                                           relocation, FALSE))
+                                           relocation, false))
            r = bfd_reloc_overflow;
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        default:
@@ -2734,7 +2794,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
        case bfd_reloc_undefined:
          info->callbacks->undefined_symbol
            (info, name, input_bfd, input_section, rel->r_offset,
-            TRUE);
+            true);
          break;
 
        case bfd_reloc_outofrange:
@@ -2769,7 +2829,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
 
       /* We already reported the error via a callback, so don't try to report
         it again by returning false.  That leads to spurious errors.  */
-      ret = TRUE;
+      ret = true;
       goto out;
     }
 
@@ -2782,7 +2842,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static bfd_boolean
+static bool
 riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
                                 struct bfd_link_info *info,
                                 struct elf_link_hash_entry *h,
@@ -2824,7 +2884,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
          || plt == NULL
          || gotplt == NULL
          || relplt == NULL)
-       return FALSE;
+       return false;
 
       /* Calculate the address of the PLT header.  */
       header_address = sec_addr (plt);
@@ -2852,10 +2912,10 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
       if (! riscv_make_plt_entry (output_bfd, got_address,
                                  header_address + h->plt.offset,
                                  plt_entry))
-       return FALSE;
+       return false;
 
       for (i = 0; i < PLT_ENTRY_INSNS; i++)
-       bfd_put_32 (output_bfd, plt_entry[i], loc + 4*i);
+       bfd_putl32 (plt_entry[i], loc + 4*i);
 
       /* Fill in the initial value of the .got.plt entry.  */
       loc = gotplt->contents + (got_address - sec_addr (gotplt));
@@ -2912,7 +2972,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
       asection *sgot;
       asection *srela;
       Elf_Internal_Rela rela;
-      bfd_boolean use_elf_append_rela = TRUE;
+      bool use_elf_append_rela = true;
 
       /* This symbol has an entry in the GOT.  Set it up.  */
 
@@ -2938,7 +2998,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
 
                  /* Do not use riscv_elf_append_rela to add dynamic
                     relocs.  */
-                 use_elf_append_rela = FALSE;
+                 use_elf_append_rela = false;
                }
 
              if (SYMBOL_REFERENCES_LOCAL (info, h))
@@ -2955,7 +3015,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
              else
                {
                  /* Generate R_RISCV_NN.  */
-                 BFD_ASSERT((h->got.offset & 1) == 0);
+                 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;
@@ -2964,7 +3024,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
          else if (bfd_link_pic (info))
            {
              /* Generate R_RISCV_NN.  */
-             BFD_ASSERT((h->got.offset & 1) == 0);
+             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;
@@ -2985,7 +3045,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
                                       + h->plt.offset),
                          htab->elf.sgot->contents
                          + (h->got.offset & ~(bfd_vma) 1));
-             return TRUE;
+             return true;
            }
        }
       else if (bfd_link_pic (info)
@@ -2996,7 +3056,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
             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.  */
-         BFD_ASSERT((h->got.offset & 1) != 0);
+         BFD_ASSERT ((h->got.offset & 1) != 0);
          asection *sec = h->root.u.def.section;
          rela.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
          rela.r_addend = (h->root.u.def.value
@@ -3005,7 +3065,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
        }
       else
        {
-         BFD_ASSERT((h->got.offset & 1) == 0);
+         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;
@@ -3056,13 +3116,13 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
       || (h == htab->elf.hgot || h == htab->elf.hplt))
     sym->st_shndx = SHN_ABS;
 
-  return TRUE;
+  return true;
 }
 
 /* Finish up local dynamic symbol handling.  We set the contents of
    various dynamic sections here.  */
 
-static bfd_boolean
+static int
 riscv_elf_finish_local_dynamic_symbol (void **slot, void *inf)
 {
   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
@@ -3073,7 +3133,7 @@ riscv_elf_finish_local_dynamic_symbol (void **slot, void *inf)
 
 /* Finish up the dynamic sections.  */
 
-static bfd_boolean
+static bool
 riscv_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
                  bfd *dynobj, asection *sdyn)
 {
@@ -3110,10 +3170,10 @@ riscv_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
 
       bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
     }
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 riscv_elf_finish_dynamic_sections (bfd *output_bfd,
                                   struct bfd_link_info *info)
 {
@@ -3130,7 +3190,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       asection *splt;
-      bfd_boolean ret;
+      bool ret;
 
       splt = htab->elf.splt;
       BFD_ASSERT (splt != NULL && sdyn != NULL);
@@ -3152,7 +3212,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
            return ret;
 
          for (i = 0; i < PLT_HEADER_INSNS; i++)
-           bfd_put_32 (output_bfd, plt_header[i], splt->contents + 4*i);
+           bfd_putl32 (plt_header[i], splt->contents + 4*i);
 
          elf_section_data (splt->output_section)->this_hdr.sh_entsize
            = PLT_ENTRY_SIZE;
@@ -3167,7 +3227,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
        {
          (*_bfd_error_handler)
            (_("discarded output section: `%pA'"), htab->elf.sgotplt);
-         return FALSE;
+         return false;
        }
 
       if (htab->elf.sgotplt->size > 0)
@@ -3202,7 +3262,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
                 riscv_elf_finish_local_dynamic_symbol,
                 info);
 
-  return TRUE;
+  return true;
 }
 
 /* Return address for Ith PLT stub in section PLT, for relocation REL
@@ -3258,14 +3318,14 @@ riscv_float_abi_string (flagword flags)
     }
 }
 
-/* The information of architecture attribute.  */
+/* The information of architecture elf attributes.  */
 static riscv_subset_list_t in_subsets;
 static riscv_subset_list_t out_subsets;
 static riscv_subset_list_t merged_subsets;
 
 /* Predicator for standard extension.  */
 
-static bfd_boolean
+static bool
 riscv_std_ext_p (const char *name)
 {
   return (strlen (name) == 1) && (name[0] != 'x') && (name[0] != 's');
@@ -3273,28 +3333,38 @@ riscv_std_ext_p (const char *name)
 
 /* Check if the versions are compatible.  */
 
-static bfd_boolean
+static bool
 riscv_version_mismatch (bfd *ibfd,
                        struct riscv_subset_t *in,
                        struct riscv_subset_t *out)
 {
   if (in == NULL || out == NULL)
-    return TRUE;
+    return true;
 
   /* Since there are no version conflicts for now, we just report
      warning when the versions are mis-matched.  */
   if (in->major_version != out->major_version
       || in->minor_version != out->minor_version)
     {
-      _bfd_error_handler
-       (_("warning: %pB: mis-matched ISA version %d.%d for '%s' "
-          "extension, the output version is %d.%d"),
-        ibfd,
-        in->major_version,
-        in->minor_version,
-        in->name,
-        out->major_version,
-        out->minor_version);
+      if ((in->major_version == RISCV_UNKNOWN_VERSION
+          && in->minor_version == RISCV_UNKNOWN_VERSION)
+         || (out->major_version == RISCV_UNKNOWN_VERSION
+             && out->minor_version == RISCV_UNKNOWN_VERSION))
+       {
+         /* Do not report the warning when the version of input
+            or output is RISCV_UNKNOWN_VERSION, since the extension
+            is added implicitly.  */
+       }
+      else
+       _bfd_error_handler
+         (_("warning: %pB: mis-matched ISA version %d.%d for '%s' "
+            "extension, the output version is %d.%d"),
+          ibfd,
+          in->major_version,
+          in->minor_version,
+          in->name,
+          out->major_version,
+          out->minor_version);
 
       /* Update the output ISA versions to the newest ones.  */
       if ((in->major_version > out->major_version)
@@ -3306,12 +3376,12 @@ riscv_version_mismatch (bfd *ibfd,
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Return true if subset is 'i' or 'e'.  */
 
-static bfd_boolean
+static bool
 riscv_i_or_e_p (bfd *ibfd,
                const char *arch,
                struct riscv_subset_t *subset)
@@ -3323,9 +3393,9 @@ riscv_i_or_e_p (bfd *ibfd,
        (_("error: %pB: corrupted ISA string '%s'.  "
           "First letter should be 'i' or 'e' but got '%s'"),
           ibfd, arch, subset->name);
-      return FALSE;
+      return false;
     }
-  return TRUE;
+  return true;
 }
 
 /* Merge standard extensions.
@@ -3335,13 +3405,12 @@ riscv_i_or_e_p (bfd *ibfd,
 
    Arguments:
      `bfd`: bfd handler.
-     `in_arch`: Raw arch string for input object.
-     `out_arch`: Raw arch string for output object.
-     `pin`: subset list for input object, and it'll skip all merged subset after
-            merge.
-     `pout`: Like `pin`, but for output object.  */
+     `in_arch`: Raw ISA string for input object.
+     `out_arch`: Raw ISA string for output object.
+     `pin`: Subset list for input object.
+     `pout`: Subset list for output object.  */
 
-static bfd_boolean
+static bool
 riscv_merge_std_ext (bfd *ibfd,
                     const char *in_arch,
                     const char *out_arch,
@@ -3355,10 +3424,10 @@ riscv_merge_std_ext (bfd *ibfd,
 
   /* First letter should be 'i' or 'e'.  */
   if (!riscv_i_or_e_p (ibfd, in_arch, in))
-    return FALSE;
+    return false;
 
   if (!riscv_i_or_e_p (ibfd, out_arch, out))
-    return FALSE;
+    return false;
 
   if (strcasecmp (in->name, out->name) != 0)
     {
@@ -3366,10 +3435,10 @@ riscv_merge_std_ext (bfd *ibfd,
       _bfd_error_handler
        (_("error: %pB: mis-matched ISA string to merge '%s' and '%s'"),
         ibfd, in->name, out->name);
-      return FALSE;
+      return false;
     }
   else if (!riscv_version_mismatch (ibfd, in, out))
-    return FALSE;
+    return false;
   else
     riscv_add_subset (&merged_subsets,
                      out->name, out->major_version, out->minor_version);
@@ -3382,7 +3451,7 @@ riscv_merge_std_ext (bfd *ibfd,
     {
       struct riscv_subset_t *ext_in, *ext_out, *ext_merged;
       char find_ext[2] = {*p, '\0'};
-      bfd_boolean find_in, find_out;
+      bool find_in, find_out;
 
       find_in = riscv_lookup_subset (&in_subsets, find_ext, &ext_in);
       find_out = riscv_lookup_subset (&out_subsets, find_ext, &ext_out);
@@ -3393,7 +3462,7 @@ riscv_merge_std_ext (bfd *ibfd,
       if (find_in
          && find_out
          && !riscv_version_mismatch (ibfd, ext_in, ext_out))
-       return FALSE;
+       return false;
 
       ext_merged = find_out ? ext_out : ext_in;
       riscv_add_subset (&merged_subsets, ext_merged->name,
@@ -3407,47 +3476,14 @@ riscv_merge_std_ext (bfd *ibfd,
   *pin = in;
   *pout = out;
 
-  return TRUE;
-}
-
-/* If C is a prefix class, then return the EXT string without the prefix.
-   Otherwise return the entire EXT string.  */
-
-static const char *
-riscv_skip_prefix (const char *ext, riscv_isa_ext_class_t c)
-{
-  switch (c)
-    {
-    case RV_ISA_CLASS_X: return &ext[1];
-    case RV_ISA_CLASS_S: return &ext[1];
-    case RV_ISA_CLASS_Z: return &ext[1];
-    default: return ext;
-    }
-}
-
-/* Compare prefixed extension names canonically.  */
-
-static int
-riscv_prefix_cmp (const char *a, const char *b)
-{
-  riscv_isa_ext_class_t ca = riscv_get_prefix_class (a);
-  riscv_isa_ext_class_t cb = riscv_get_prefix_class (b);
-
-  /* Extension name without prefix  */
-  const char *anp = riscv_skip_prefix (a, ca);
-  const char *bnp = riscv_skip_prefix (b, cb);
-
-  if (ca == cb)
-    return strcasecmp (anp, bnp);
-
-  return (int)ca - (int)cb;
+  return true;
 }
 
 /* Merge multi letter extensions.  PIN is a pointer to the head of the input
    object subset list.  Likewise for POUT and the output object.  Return TRUE
    on success and FALSE when a conflict is found.  */
 
-static bfd_boolean
+static bool
 riscv_merge_multi_letter_ext (bfd *ibfd,
                              riscv_subset_t **pin,
                              riscv_subset_t **pout)
@@ -3460,7 +3496,7 @@ riscv_merge_multi_letter_ext (bfd *ibfd,
 
   while (in && out)
     {
-      cmp = riscv_prefix_cmp (in->name, out->name);
+      cmp = riscv_compare_subsets (in->name, out->name);
 
       if (cmp < 0)
        {
@@ -3480,7 +3516,7 @@ riscv_merge_multi_letter_ext (bfd *ibfd,
        {
          /* Both present, check version and increment both.  */
          if (!riscv_version_mismatch (ibfd, in, out))
-           return FALSE;
+           return false;
 
          riscv_add_subset (&merged_subsets, out->name, out->major_version,
                            out->minor_version);
@@ -3489,20 +3525,20 @@ riscv_merge_multi_letter_ext (bfd *ibfd,
        }
     }
 
-  if (in || out) {
-    /* If we're here, either `in' or `out' is running longer than
-       the other. So, we need to append the corresponding tail.  */
-    tail = in ? in : out;
-
-    while (tail)
-      {
-       riscv_add_subset (&merged_subsets, tail->name, tail->major_version,
-                         tail->minor_version);
-       tail = tail->next;
-      }
-  }
+  if (in || out)
+    {
+      /* If we're here, either `in' or `out' is running longer than
+        the other. So, we need to append the corresponding tail.  */
+      tail = in ? in : out;
+      while (tail)
+       {
+         riscv_add_subset (&merged_subsets, tail->name, tail->major_version,
+                           tail->minor_version);
+         tail = tail->next;
+       }
+    }
 
-  return TRUE;
+  return true;
 }
 
 /* Merge Tag_RISCV_arch attribute.  */
@@ -3526,11 +3562,13 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
   rpe_in.error_handler = _bfd_error_handler;
   rpe_in.xlen = &xlen_in;
   rpe_in.get_default_version = NULL;
+  rpe_in.check_unknown_prefixed_ext = false;
 
   rpe_out.subset_list = &out_subsets;
   rpe_out.error_handler = _bfd_error_handler;
   rpe_out.xlen = &xlen_out;
   rpe_out.get_default_version = NULL;
+  rpe_out.check_unknown_prefixed_ext = false;
 
   if (in_arch == NULL && out_arch == NULL)
     return NULL;
@@ -3541,7 +3579,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
   if (in_arch != NULL && out_arch == NULL)
     return in_arch;
 
-  /* Parse subset from arch string.  */
+  /* Parse subset from ISA string.  */
   if (!riscv_parse_subset (&rpe_in, in_arch))
     return NULL;
 
@@ -3598,26 +3636,26 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
 /* Merge object attributes from IBFD into output_bfd of INFO.
    Raise an error if there are conflicting attributes.  */
 
-static bfd_boolean
+static bool
 riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
 {
   bfd *obfd = info->output_bfd;
   obj_attribute *in_attr;
   obj_attribute *out_attr;
-  bfd_boolean result = TRUE;
-  bfd_boolean priv_attrs_merged = FALSE;
+  bool result = true;
+  bool priv_attrs_merged = false;
   const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section;
   unsigned int i;
 
   /* Skip linker created files.  */
   if (ibfd->flags & BFD_LINKER_CREATED)
-    return TRUE;
+    return true;
 
   /* Skip any input that doesn't have an attribute section.
      This enables to link object files without attribute section with
      any others.  */
   if (bfd_get_section_by_name (ibfd, sec_name) == NULL)
-    return TRUE;
+    return true;
 
   if (!elf_known_obj_attributes_proc (obfd)[0].i)
     {
@@ -3630,7 +3668,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
         initialized.  */
       out_attr[0].i = 1;
 
-      return TRUE;
+      return true;
     }
 
   in_attr = elf_known_obj_attributes_proc (ibfd);
@@ -3646,14 +3684,14 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
        else if (in_attr[Tag_RISCV_arch].s
                 && out_attr[Tag_RISCV_arch].s)
          {
-           /* Check arch compatible.  */
+           /* Check compatible.  */
            char *merged_arch =
                riscv_merge_arch_attr_info (ibfd,
                                            in_attr[Tag_RISCV_arch].s,
                                            out_attr[Tag_RISCV_arch].s);
            if (merged_arch == NULL)
              {
-               result = FALSE;
+               result = false;
                out_attr[Tag_RISCV_arch].s = "";
              }
            else
@@ -3664,16 +3702,16 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
       case Tag_RISCV_priv_spec:
       case Tag_RISCV_priv_spec_minor:
       case Tag_RISCV_priv_spec_revision:
-       /* If we have handled the priv attributes, then skip it.  */
+       /* If we have handled the privileged elf attributes, then skip it.  */
        if (!priv_attrs_merged)
          {
            unsigned int Tag_a = Tag_RISCV_priv_spec;
            unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
            unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
-           enum riscv_priv_spec_class in_priv_spec;
-           enum riscv_priv_spec_class out_priv_spec;
+           enum riscv_spec_class in_priv_spec = PRIV_SPEC_CLASS_NONE;
+           enum riscv_spec_class out_priv_spec = PRIV_SPEC_CLASS_NONE;
 
-           /* Get the priv spec class from elf attribute numbers.  */
+           /* Get the privileged spec class from elf attributes.  */
            riscv_get_priv_spec_class_from_numbers (in_attr[Tag_a].i,
                                                    in_attr[Tag_b].i,
                                                    in_attr[Tag_c].i,
@@ -3683,7 +3721,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
                                                    out_attr[Tag_c].i,
                                                    &out_priv_spec);
 
-           /* Allow to link the object without the priv specs.  */
+           /* Allow to link the object without the privileged specs.  */
            if (out_priv_spec == PRIV_SPEC_CLASS_NONE)
              {
                out_attr[Tag_a].i = in_attr[Tag_a].i;
@@ -3694,7 +3732,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
                     && in_priv_spec != out_priv_spec)
              {
                _bfd_error_handler
-                 (_("warning: %pB use privilege spec version %u.%u.%u but "
+                 (_("warning: %pB use privileged spec version %u.%u.%u but "
                     "the output use version %u.%u.%u"),
                   ibfd,
                   in_attr[Tag_a].i,
@@ -3704,19 +3742,18 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
                   out_attr[Tag_b].i,
                   out_attr[Tag_c].i);
 
-               /* The priv spec v1.9.1 can not be linked with other spec
-                  versions since the conflicts.  We plan to drop the
-                  v1.9.1 in a year or two, so this confict should be
-                  removed in the future.  */
+               /* The privileged spec v1.9.1 can not be linked with others
+                  since the conflicts, so we plan to drop it in a year or
+                  two.  */
                if (in_priv_spec == PRIV_SPEC_CLASS_1P9P1
                    || out_priv_spec == PRIV_SPEC_CLASS_1P9P1)
                  {
                    _bfd_error_handler
-                     (_("warning: privilege spec version 1.9.1 can not be "
+                     (_("warning: privileged spec version 1.9.1 can not be "
                         "linked with other spec versions"));
                  }
 
-               /* Update the output priv spec to the newest one.  */
+               /* Update the output privileged spec to the newest one.  */
                if (in_priv_spec > out_priv_spec)
                  {
                    out_attr[Tag_a].i = in_attr[Tag_a].i;
@@ -3724,7 +3761,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
                    out_attr[Tag_c].i = in_attr[Tag_c].i;
                  }
              }
-           priv_attrs_merged = TRUE;
+           priv_attrs_merged = true;
          }
        break;
 
@@ -3743,7 +3780,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
              (_("error: %pB use %u-byte stack aligned but the output "
                 "use %u-byte stack aligned"),
               ibfd, in_attr[i].i, out_attr[i].i);
-           result = FALSE;
+           result = false;
          }
        break;
 
@@ -3758,7 +3795,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
 
   /* Merge Tag_compatibility attributes and any common GNU ones.  */
   if (!_bfd_elf_merge_object_attributes (ibfd, info))
-    return FALSE;
+    return false;
 
   /* Check for any attributes not known on RISC-V.  */
   result &= _bfd_elf_merge_unknown_attribute_list (ibfd, obfd);
@@ -3769,14 +3806,14 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
-static bfd_boolean
+static bool
 _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 {
   bfd *obfd = info->output_bfd;
   flagword new_flags, old_flags;
 
   if (!is_riscv_elf (ibfd) || !is_riscv_elf (obfd))
-    return TRUE;
+    return true;
 
   if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
     {
@@ -3784,24 +3821,14 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
        (_("%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;
+      return false;
     }
 
   if (!_bfd_elf_merge_object_attributes (ibfd, info))
-    return FALSE;
+    return false;
 
   if (!riscv_merge_attributes (ibfd, info))
-    return FALSE;
-
-  new_flags = elf_elfheader (ibfd)->e_flags;
-  old_flags = elf_elfheader (obfd)->e_flags;
-
-  if (! elf_flags_init (obfd))
-    {
-      elf_flags_init (obfd) = TRUE;
-      elf_elfheader (obfd)->e_flags = new_flags;
-      return TRUE;
-    }
+    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
@@ -3812,23 +3839,35 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
      case, there is no need to check for code specific flags.  */
   if (!(ibfd->flags & DYNAMIC))
     {
-      bfd_boolean null_input_bfd = TRUE;
-      bfd_boolean only_data_sections = TRUE;
+      bool null_input_bfd = true;
+      bool only_data_sections = true;
       asection *sec;
 
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
        {
+         null_input_bfd = false;
+
          if ((bfd_section_flags (sec)
               & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
              == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
-           only_data_sections = FALSE;
-
-         null_input_bfd = FALSE;
-         break;
+           {
+             only_data_sections = false;
+             break;
+           }
        }
 
       if (null_input_bfd || only_data_sections)
-       return TRUE;
+       return true;
+    }
+
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  old_flags = elf_elfheader (obfd)->e_flags;
+
+  if (!elf_flags_init (obfd))
+    {
+      elf_flags_init (obfd) = true;
+      elf_elfheader (obfd)->e_flags = new_flags;
+      return true;
     }
 
   /* Disallow linking different float ABIs.  */
@@ -3852,16 +3891,16 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   /* Allow linking RVC and non-RVC, and keep the RVC flag.  */
   elf_elfheader (obfd)->e_flags |= new_flags & EF_RISCV_RVC;
 
-  return TRUE;
+  return true;
 
  fail:
   bfd_set_error (bfd_error_bad_value);
-  return FALSE;
+  return false;
 }
 
 /* Delete some bytes from a section while relaxing.  */
 
-static bfd_boolean
+static bool
 riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count,
                          struct bfd_link_info *link_info)
 {
@@ -3924,8 +3963,9 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count,
         call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
         the same symbol (which is __wrap_SYMBOL), but still exist as two
         different symbols in 'sym_hashes', we don't want to adjust
-        the global symbol __wrap_SYMBOL twice.  */
-      /* The same problem occurs with symbols that are versioned_hidden, as
+        the global symbol __wrap_SYMBOL twice.
+
+        The same problem occurs with symbols that are versioned_hidden, as
         foo becomes an alias for foo@BAR, and hence they need the same
         treatment.  */
       if (link_info->wrap_hash != NULL
@@ -3964,7 +4004,7 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count,
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* A second format for recording PC-relative hi relocations.  This stores the
@@ -3978,7 +4018,7 @@ struct riscv_pcgp_hi_reloc
   bfd_vma hi_addr;
   unsigned hi_sym;
   asection *sym_sec;
-  bfd_boolean undefined_weak;
+  bool undefined_weak;
   riscv_pcgp_hi_reloc *next;
 };
 
@@ -3997,12 +4037,12 @@ typedef struct
 
 /* Initialize the pcgp reloc info in P.  */
 
-static bfd_boolean
+static bool
 riscv_init_pcgp_relocs (riscv_pcgp_relocs *p)
 {
   p->hi = NULL;
   p->lo = NULL;
-  return TRUE;
+  return true;
 }
 
 /* Free the pcgp reloc info in P.  */
@@ -4015,14 +4055,14 @@ riscv_free_pcgp_relocs (riscv_pcgp_relocs *p,
   riscv_pcgp_hi_reloc *c;
   riscv_pcgp_lo_reloc *l;
 
-  for (c = p->hi; c != NULL;)
+  for (c = p->hi; c != NULL; )
     {
       riscv_pcgp_hi_reloc *next = c->next;
       free (c);
       c = next;
     }
 
-  for (l = p->lo; l != NULL;)
+  for (l = p->lo; l != NULL; )
     {
       riscv_pcgp_lo_reloc *next = l->next;
       free (l);
@@ -4034,15 +4074,15 @@ riscv_free_pcgp_relocs (riscv_pcgp_relocs *p,
    The HI_ADDEND, HI_ADDR, HI_SYM, and SYM_SEC args contain info required to
    relax the corresponding lo part reloc.  */
 
-static bfd_boolean
+static bool
 riscv_record_pcgp_hi_reloc (riscv_pcgp_relocs *p, bfd_vma hi_sec_off,
                            bfd_vma hi_addend, bfd_vma hi_addr,
                            unsigned hi_sym, asection *sym_sec,
-                           bfd_boolean undefined_weak)
+                           bool undefined_weak)
 {
-  riscv_pcgp_hi_reloc *new = bfd_malloc (sizeof(*new));
+  riscv_pcgp_hi_reloc *new = bfd_malloc (sizeof (*new));
   if (!new)
-    return FALSE;
+    return false;
   new->hi_sec_off = hi_sec_off;
   new->hi_addend = hi_addend;
   new->hi_addr = hi_addr;
@@ -4051,14 +4091,14 @@ riscv_record_pcgp_hi_reloc (riscv_pcgp_relocs *p, bfd_vma hi_sec_off,
   new->undefined_weak = undefined_weak;
   new->next = p->hi;
   p->hi = new;
-  return TRUE;
+  return true;
 }
 
 /* Look up hi part pcgp reloc info in P, using HI_SEC_OFF as the lookup index.
    This is used by a lo part reloc to find the corresponding hi part reloc.  */
 
 static riscv_pcgp_hi_reloc *
-riscv_find_pcgp_hi_reloc(riscv_pcgp_relocs *p, bfd_vma hi_sec_off)
+riscv_find_pcgp_hi_reloc (riscv_pcgp_relocs *p, bfd_vma hi_sec_off)
 {
   riscv_pcgp_hi_reloc *c;
 
@@ -4071,55 +4111,55 @@ riscv_find_pcgp_hi_reloc(riscv_pcgp_relocs *p, bfd_vma hi_sec_off)
 /* Record pcgp lo part reloc info in P, using HI_SEC_OFF as the lookup info.
    This is used to record relocs that can't be relaxed.  */
 
-static bfd_boolean
+static bool
 riscv_record_pcgp_lo_reloc (riscv_pcgp_relocs *p, bfd_vma hi_sec_off)
 {
-  riscv_pcgp_lo_reloc *new = bfd_malloc (sizeof(*new));
+  riscv_pcgp_lo_reloc *new = bfd_malloc (sizeof (*new));
   if (!new)
-    return FALSE;
+    return false;
   new->hi_sec_off = hi_sec_off;
   new->next = p->lo;
   p->lo = new;
-  return TRUE;
+  return true;
 }
 
 /* Look up lo part pcgp reloc info in P, using HI_SEC_OFF as the lookup index.
    This is used by a hi part reloc to find the corresponding lo part reloc.  */
 
-static bfd_boolean
+static bool
 riscv_find_pcgp_lo_reloc (riscv_pcgp_relocs *p, bfd_vma hi_sec_off)
 {
   riscv_pcgp_lo_reloc *c;
 
   for (c = p->lo; c != NULL; c = c->next)
     if (c->hi_sec_off == hi_sec_off)
-      return TRUE;
-  return FALSE;
+      return true;
+  return false;
 }
 
-typedef bfd_boolean (*relax_func_t) (bfd *, asection *, asection *,
-                                    struct bfd_link_info *,
-                                    Elf_Internal_Rela *,
-                                    bfd_vma, bfd_vma, bfd_vma, bfd_boolean *,
-                                    riscv_pcgp_relocs *,
-                                    bfd_boolean undefined_weak);
+typedef bool (*relax_func_t) (bfd *, asection *, asection *,
+                             struct bfd_link_info *,
+                             Elf_Internal_Rela *,
+                             bfd_vma, bfd_vma, bfd_vma, bool *,
+                             riscv_pcgp_relocs *,
+                             bool undefined_weak);
 
 /* Relax AUIPC + JALR into JAL.  */
 
-static bfd_boolean
+static bool
 _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
                       struct bfd_link_info *link_info,
                       Elf_Internal_Rela *rel,
                       bfd_vma symval,
                       bfd_vma max_alignment,
                       bfd_vma reserve_size ATTRIBUTE_UNUSED,
-                      bfd_boolean *again,
+                      bool *again,
                       riscv_pcgp_relocs *pcgp_relocs ATTRIBUTE_UNUSED,
-                      bfd_boolean undefined_weak ATTRIBUTE_UNUSED)
+                      bool undefined_weak ATTRIBUTE_UNUSED)
 {
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   bfd_vma foff = symval - (sec_addr (sec) + rel->r_offset);
-  bfd_boolean near_zero = (symval + RISCV_IMM_REACH/2) < RISCV_IMM_REACH;
+  bool near_zero = (symval + RISCV_IMM_REACH / 2) < RISCV_IMM_REACH;
   bfd_vma auipc, jalr;
   int rd, r_type, len = 4, rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
 
@@ -4127,7 +4167,7 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
      cause the PC-relative offset to later increase, so we need to add in the
      max alignment of any section inclusive from the call to the target.
      Otherwise, we only need to use the alignment of the current section.  */
-  if (VALID_UJTYPE_IMM (foff))
+  if (VALID_JTYPE_IMM (foff))
     {
       if (sym_sec->output_section == sec->output_section
          && sym_sec->output_section != bfd_abs_section_ptr)
@@ -4136,16 +4176,16 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
     }
 
   /* See if this function call can be shortened.  */
-  if (!VALID_UJTYPE_IMM (foff) && !(!bfd_link_pic (link_info) && near_zero))
-    return TRUE;
+  if (!VALID_JTYPE_IMM (foff) && !(!bfd_link_pic (link_info) && near_zero))
+    return true;
 
   /* Shorten the function call.  */
   BFD_ASSERT (rel->r_offset + 8 <= sec->size);
 
-  auipc = bfd_get_32 (abfd, contents + rel->r_offset);
-  jalr = bfd_get_32 (abfd, contents + rel->r_offset + 4);
+  auipc = bfd_getl32 (contents + rel->r_offset);
+  jalr = bfd_getl32 (contents + rel->r_offset + 4);
   rd = (jalr >> OP_SH_RD) & OP_MASK_RD;
-  rvc = rvc && VALID_RVC_J_IMM (foff);
+  rvc = rvc && VALID_CJTYPE_IMM (foff);
 
   /* C.J exists on RV32 and RV64, but C.JAL is RV32-only.  */
   rvc = rvc && (rd == 0 || (rd == X_RA && ARCH_SIZE == 32));
@@ -4157,15 +4197,15 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
       auipc = rd == 0 ? MATCH_C_J : MATCH_C_JAL;
       len = 2;
     }
-  else if (VALID_UJTYPE_IMM (foff))
+  else if (VALID_JTYPE_IMM (foff))
     {
       /* Relax to JAL rd, addr.  */
       r_type = R_RISCV_JAL;
       auipc = MATCH_JAL | (rd << OP_SH_RD);
     }
-  else /* near_zero */
+  else
     {
-      /* Relax to JALR rd, x0, addr.  */
+      /* Near zero, relax to JALR rd, x0, addr.  */
       r_type = R_RISCV_LO12_I;
       auipc = MATCH_JALR | (rd << OP_SH_RD);
     }
@@ -4173,10 +4213,10 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
   /* Replace the R_RISCV_CALL reloc.  */
   rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), r_type);
   /* Replace the AUIPC.  */
-  bfd_put (8 * len, abfd, auipc, contents + rel->r_offset);
+  riscv_put_insn (8 * len, auipc, contents + rel->r_offset);
 
   /* Delete unnecessary JALR.  */
-  *again = TRUE;
+  *again = true;
   return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len,
                                   link_info);
 }
@@ -4198,9 +4238,9 @@ _bfd_riscv_get_max_alignment (asection *sec)
   return (bfd_vma) 1 << max_alignment_power;
 }
 
-/* Relax non-PIC global variable references.  */
+/* Relax non-PIC global variable references to GP-relative references.  */
 
-static bfd_boolean
+static bool
 _bfd_riscv_relax_lui (bfd *abfd,
                      asection *sec,
                      asection *sym_sec,
@@ -4209,9 +4249,9 @@ _bfd_riscv_relax_lui (bfd *abfd,
                      bfd_vma symval,
                      bfd_vma max_alignment,
                      bfd_vma reserve_size,
-                     bfd_boolean *again,
+                     bool *again,
                      riscv_pcgp_relocs *pcgp_relocs ATTRIBUTE_UNUSED,
-                     bfd_boolean undefined_weak)
+                     bool undefined_weak)
 {
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   bfd_vma gp = riscv_global_pointer_value (link_info);
@@ -4224,8 +4264,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
       /* If gp and the symbol are in the same output section, which is not the
         abs section, then consider only that output section's alignment.  */
       struct bfd_link_hash_entry *h =
-       bfd_link_hash_lookup (link_info->hash, RISCV_GP_SYMBOL, FALSE, FALSE,
-                             TRUE);
+       bfd_link_hash_lookup (link_info->hash, RISCV_GP_SYMBOL, false, false,
+                             true);
       if (h->u.def.section->output_section == sym_sec->output_section
          && sym_sec->output_section != bfd_abs_section_ptr)
        max_alignment = (bfd_vma) 1 << sym_sec->output_section->alignment_power;
@@ -4247,30 +4287,30 @@ _bfd_riscv_relax_lui (bfd *abfd,
          if (undefined_weak)
            {
              /* Change the RS1 to zero.  */
-             bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset);
+             bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
              insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
-             bfd_put_32 (abfd, insn, contents + rel->r_offset);
+             bfd_putl32 (insn, contents + rel->r_offset);
            }
          else
            rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I);
-         return TRUE;
+         return true;
 
        case R_RISCV_LO12_S:
          if (undefined_weak)
            {
              /* Change the RS1 to zero.  */
-             bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset);
+             bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
              insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
-             bfd_put_32 (abfd, insn, contents + rel->r_offset);
+             bfd_putl32 (insn, contents + rel->r_offset);
            }
          else
            rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S);
-         return TRUE;
+         return true;
 
        case R_RISCV_HI20:
          /* We can delete the unnecessary LUI and reloc.  */
          rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
-         *again = TRUE;
+         *again = true;
          return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4,
                                           link_info);
 
@@ -4286,34 +4326,34 @@ _bfd_riscv_relax_lui (bfd *abfd,
 
   if (use_rvc
       && ELFNN_R_TYPE (rel->r_info) == R_RISCV_HI20
-      && VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (symval))
-      && VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (symval)
+      && VALID_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (symval))
+      && VALID_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (symval)
                            + (link_info->relro ? 2 * ELF_MAXPAGESIZE
                               : ELF_MAXPAGESIZE)))
     {
       /* Replace LUI with C.LUI if legal (i.e., rd != x0 and rd != x2/sp).  */
-      bfd_vma lui = bfd_get_32 (abfd, contents + rel->r_offset);
+      bfd_vma lui = bfd_getl32 (contents + rel->r_offset);
       unsigned rd = ((unsigned)lui >> OP_SH_RD) & OP_MASK_RD;
       if (rd == 0 || rd == X_SP)
-       return TRUE;
+       return true;
 
       lui = (lui & (OP_MASK_RD << OP_SH_RD)) | MATCH_C_LUI;
-      bfd_put_32 (abfd, lui, contents + rel->r_offset);
+      bfd_putl32 (lui, contents + rel->r_offset);
 
       /* Replace the R_RISCV_HI20 reloc.  */
       rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_RVC_LUI);
 
-      *again = TRUE;
+      *again = true;
       return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2,
                                       link_info);
     }
 
-  return TRUE;
+  return true;
 }
 
-/* Relax non-PIC TLS references.  */
+/* Relax non-PIC TLS references to TP-relative references.  */
 
-static bfd_boolean
+static bool
 _bfd_riscv_relax_tls_le (bfd *abfd,
                         asection *sec,
                         asection *sym_sec ATTRIBUTE_UNUSED,
@@ -4322,30 +4362,30 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
                         bfd_vma symval,
                         bfd_vma max_alignment ATTRIBUTE_UNUSED,
                         bfd_vma reserve_size ATTRIBUTE_UNUSED,
-                        bfd_boolean *again,
+                        bool *again,
                         riscv_pcgp_relocs *prcel_relocs ATTRIBUTE_UNUSED,
-                        bfd_boolean undefined_weak ATTRIBUTE_UNUSED)
+                        bool undefined_weak ATTRIBUTE_UNUSED)
 {
   /* See if this symbol is in range of tp.  */
   if (RISCV_CONST_HIGH_PART (tpoff (link_info, symval)) != 0)
-    return TRUE;
+    return true;
 
   BFD_ASSERT (rel->r_offset + 4 <= sec->size);
   switch (ELFNN_R_TYPE (rel->r_info))
     {
     case R_RISCV_TPREL_LO12_I:
       rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TPREL_I);
-      return TRUE;
+      return true;
 
     case R_RISCV_TPREL_LO12_S:
       rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TPREL_S);
-      return TRUE;
+      return true;
 
     case R_RISCV_TPREL_HI20:
     case R_RISCV_TPREL_ADD:
       /* We can delete the unnecessary instruction and reloc.  */
       rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
-      *again = TRUE;
+      *again = true;
       return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, link_info);
 
     default:
@@ -4353,9 +4393,10 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
     }
 }
 
-/* Implement R_RISCV_ALIGN by deleting excess alignment NOPs.  */
+/* Implement R_RISCV_ALIGN by deleting excess alignment NOPs.
+   Once we've handled an R_RISCV_ALIGN, we can't relax anything else.  */
 
-static bfd_boolean
+static bool
 _bfd_riscv_relax_align (bfd *abfd, asection *sec,
                        asection *sym_sec,
                        struct bfd_link_info *link_info,
@@ -4363,9 +4404,9 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
                        bfd_vma symval,
                        bfd_vma max_alignment ATTRIBUTE_UNUSED,
                        bfd_vma reserve_size ATTRIBUTE_UNUSED,
-                       bfd_boolean *again ATTRIBUTE_UNUSED,
+                       bool *again ATTRIBUTE_UNUSED,
                        riscv_pcgp_relocs *pcrel_relocs ATTRIBUTE_UNUSED,
-                       bfd_boolean undefined_weak ATTRIBUTE_UNUSED)
+                       bool undefined_weak ATTRIBUTE_UNUSED)
 {
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   bfd_vma alignment = 1, pos;
@@ -4376,9 +4417,6 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
   bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
   bfd_vma nop_bytes = aligned_addr - symval;
 
-  /* Once we've handled an R_RISCV_ALIGN, we can't relax anything else.  */
-  sec->sec_flg0 = TRUE;
-
   /* Make sure there are enough NOPs to actually achieve the alignment.  */
   if (rel->r_addend < nop_bytes)
     {
@@ -4388,7 +4426,7 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
         abfd, sym_sec, (uint64_t) rel->r_offset,
         (int64_t) nop_bytes, (int64_t) alignment, (int64_t) rel->r_addend);
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
   /* Delete the reloc.  */
@@ -4396,15 +4434,15 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
 
   /* If the number of NOPs is already correct, there's nothing to do.  */
   if (nop_bytes == rel->r_addend)
-    return TRUE;
+    return true;
 
   /* Write as many RISC-V NOPs as we need.  */
   for (pos = 0; pos < (nop_bytes & -4); pos += 4)
-    bfd_put_32 (abfd, RISCV_NOP, contents + rel->r_offset + pos);
+    bfd_putl32 (RISCV_NOP, contents + rel->r_offset + pos);
 
   /* Write a final RVC NOP if need be.  */
   if (nop_bytes % 4 != 0)
-    bfd_put_16 (abfd, RVC_NOP, contents + rel->r_offset + pos);
+    bfd_putl16 (RVC_NOP, contents + rel->r_offset + pos);
 
   /* Delete the excess bytes.  */
   return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
@@ -4413,18 +4451,18 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
 
 /* Relax PC-relative references to GP-relative references.  */
 
-static bfd_boolean
-_bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
-                     asection *sec,
-                     asection *sym_sec,
-                     struct bfd_link_info *link_info,
-                     Elf_Internal_Rela *rel,
-                     bfd_vma symval,
-                     bfd_vma max_alignment,
-                     bfd_vma reserve_size,
-                     bfd_boolean *again ATTRIBUTE_UNUSED,
-                     riscv_pcgp_relocs *pcgp_relocs,
-                     bfd_boolean undefined_weak)
+static bool
+_bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
+                    asection *sec,
+                    asection *sym_sec,
+                    struct bfd_link_info *link_info,
+                    Elf_Internal_Rela *rel,
+                    bfd_vma symval,
+                    bfd_vma max_alignment,
+                    bfd_vma reserve_size,
+                    bool *again ATTRIBUTE_UNUSED,
+                    riscv_pcgp_relocs *pcgp_relocs,
+                    bool undefined_weak)
 {
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   bfd_vma gp = riscv_global_pointer_value (link_info);
@@ -4432,7 +4470,7 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
   BFD_ASSERT (rel->r_offset + 4 <= sec->size);
 
   /* Chain the _LO relocs to their cooresponding _HI reloc to compute the
-   * actual target address.  */
+     actual target address.  */
   riscv_pcgp_hi_reloc hi_reloc;
   memset (&hi_reloc, 0, sizeof (hi_reloc));
   switch (ELFNN_R_TYPE (rel->r_info))
@@ -4450,7 +4488,7 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
        if (hi == NULL)
          {
            riscv_record_pcgp_lo_reloc (pcgp_relocs, hi_sec_off);
-           return TRUE;
+           return true;
          }
 
        hi_reloc = *hi;
@@ -4469,12 +4507,12 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
       /* Mergeable symbols and code might later move out of range.  */
       if (! undefined_weak
          && sym_sec->flags & (SEC_MERGE | SEC_CODE))
-       return TRUE;
+       return true;
 
       /* If the cooresponding lo relocation has already been seen then it's not
-       * safe to relax this relocation.  */
+         safe to relax this relocation.  */
       if (riscv_find_pcgp_lo_reloc (pcgp_relocs, rel->r_offset))
-       return TRUE;
+       return true;
 
       break;
 
@@ -4487,8 +4525,8 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
       /* If gp and the symbol are in the same output section, which is not the
         abs section, then consider only that output section's alignment.  */
       struct bfd_link_hash_entry *h =
-       bfd_link_hash_lookup (link_info->hash, RISCV_GP_SYMBOL, FALSE, FALSE,
-                             TRUE);
+       bfd_link_hash_lookup (link_info->hash, RISCV_GP_SYMBOL, false, false,
+                             true);
       if (h->u.def.section->output_section == sym_sec->output_section
          && sym_sec->output_section != bfd_abs_section_ptr)
        max_alignment = (bfd_vma) 1 << sym_sec->output_section->alignment_power;
@@ -4511,9 +4549,9 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
            {
              /* Change the RS1 to zero, and then modify the relocation
                 type to R_RISCV_LO12_I.  */
-             bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset);
+             bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
              insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
-             bfd_put_32 (abfd, insn, contents + rel->r_offset);
+             bfd_putl32 (insn, contents + rel->r_offset);
              rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LO12_I);
              rel->r_addend = hi_reloc.hi_addend;
            }
@@ -4522,16 +4560,16 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
              rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I);
              rel->r_addend += hi_reloc.hi_addend;
            }
-         return TRUE;
+         return true;
 
        case R_RISCV_PCREL_LO12_S:
          if (undefined_weak)
            {
              /* Change the RS1 to zero, and then modify the relocation
                 type to R_RISCV_LO12_S.  */
-             bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset);
+             bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
              insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
-             bfd_put_32 (abfd, insn, contents + rel->r_offset);
+             bfd_putl32 (insn, contents + rel->r_offset);
              rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LO12_S);
              rel->r_addend = hi_reloc.hi_addend;
            }
@@ -4540,7 +4578,7 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
              rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S);
              rel->r_addend += hi_reloc.hi_addend;
            }
-         return TRUE;
+         return true;
 
        case R_RISCV_PCREL_HI20:
          riscv_record_pcgp_hi_reloc (pcgp_relocs,
@@ -4553,19 +4591,19 @@ _bfd_riscv_relax_pc  (bfd *abfd ATTRIBUTE_UNUSED,
          /* We can delete the unnecessary AUIPC and reloc.  */
          rel->r_info = ELFNN_R_INFO (0, R_RISCV_DELETE);
          rel->r_addend = 4;
-         return TRUE;
+         return true;
 
        default:
          abort ();
        }
     }
 
-  return TRUE;
+  return true;
 }
 
-/* Relax PC-relative references to GP-relative references.  */
+/* Delete the bytes for R_RISCV_DELETE.  */
 
-static bfd_boolean
+static bool
 _bfd_riscv_relax_delete (bfd *abfd,
                         asection *sec,
                         asection *sym_sec ATTRIBUTE_UNUSED,
@@ -4574,44 +4612,86 @@ _bfd_riscv_relax_delete (bfd *abfd,
                         bfd_vma symval ATTRIBUTE_UNUSED,
                         bfd_vma max_alignment ATTRIBUTE_UNUSED,
                         bfd_vma reserve_size ATTRIBUTE_UNUSED,
-                        bfd_boolean *again ATTRIBUTE_UNUSED,
+                        bool *again,
                         riscv_pcgp_relocs *pcgp_relocs ATTRIBUTE_UNUSED,
-                        bfd_boolean undefined_weak ATTRIBUTE_UNUSED)
+                        bool undefined_weak ATTRIBUTE_UNUSED)
 {
-  if (!riscv_relax_delete_bytes(abfd, sec, rel->r_offset, rel->r_addend,
-                               link_info))
-    return FALSE;
-  rel->r_info = ELFNN_R_INFO(0, R_RISCV_NONE);
-  return TRUE;
+  if (!riscv_relax_delete_bytes (abfd, sec, rel->r_offset, rel->r_addend,
+                                link_info))
+    return false;
+  rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
+  *again = true;
+  return true;
 }
 
-/* Relax a section.  Pass 0 shortens code sequences unless disabled.  Pass 1
-   deletes the bytes that pass 0 made obselete.  Pass 2, which cannot be
-   disabled, handles code alignment directives.  */
+/* Called by after_allocation to set the information of data segment
+   before relaxing.  */
 
-static bfd_boolean
+void
+bfd_elfNN_riscv_set_data_segment_info (struct bfd_link_info *info,
+                                       int *data_segment_phase)
+{
+  struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+  htab->data_segment_phase = data_segment_phase;
+}
+
+/* Called by after_allocation to check if we need to run the whole
+   relaxations again.  */
+
+bool
+bfd_elfNN_riscv_restart_relax_sections (struct bfd_link_info *info)
+{
+  struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+  bool restart = htab->restart_relax;
+  /* Reset the flag.  */
+  htab->restart_relax = false;
+  return restart;
+}
+
+/* Relax a section.
+
+   Pass 0: Shortens code sequences for LUI/CALL/TPREL relocs.
+   Pass 1: Shortens code sequences for PCREL relocs.
+   Pass 2: Deletes the bytes that pass 1 made obsolete.
+   Pass 3: Which cannot be disabled, handles code alignment directives.
+
+   The `again` is used to determine whether the relax pass itself needs to
+   run again.  And the `restart_relax` is used to determine if we need to
+   run the whole relax passes again from 0 to 2.  Once we have deleted the
+   code between relax pass 0 to 2, the restart_relax will be set to TRUE,
+   and we should run the whole relaxations again to give them more chances
+   to shorten the code.
+
+   Since we can't relax anything else once we start to handle the alignments,
+   we will only enter into the relax pass 3 when the restart_relax is FALSE.  */
+
+static bool
 _bfd_riscv_relax_section (bfd *abfd, asection *sec,
                          struct bfd_link_info *info,
-                         bfd_boolean *again)
+                         bool *again)
 {
   Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
   struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
   struct bfd_elf_section_data *data = elf_section_data (sec);
   Elf_Internal_Rela *relocs;
-  bfd_boolean ret = FALSE;
+  bool ret = false;
   unsigned int i;
   bfd_vma max_alignment, reserve_size = 0;
   riscv_pcgp_relocs pcgp_relocs;
 
-  *again = FALSE;
+  *again = false;
 
   if (bfd_link_relocatable (info)
-      || sec->sec_flg0
       || (sec->flags & SEC_RELOC) == 0
       || sec->reloc_count == 0
       || (info->disable_target_specific_optimizations
-         && info->relax_pass < 2))
-    return TRUE;
+         && info->relax_pass < 2)
+      || (htab->restart_relax
+         && info->relax_pass == 3)
+      /* The exp_seg_relro_adjust is enum phase_enum (0x4),
+        and defined in ld/ldexp.h.  */
+      || *(htab->data_segment_phase) == 4)
+    return true;
 
   riscv_init_pcgp_relocs (&pcgp_relocs);
 
@@ -4643,7 +4723,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
       int type = ELFNN_R_TYPE (rel->r_info);
       bfd_vma symval;
       char symtype;
-      bfd_boolean undefined_weak = FALSE;
+      bool undefined_weak = false;
 
       relax_func = NULL;
       if (info->relax_pass == 0)
@@ -4664,7 +4744,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
            continue;
        }
       else if (info->relax_pass == 1
-              && !bfd_link_pic(info)
+              && !bfd_link_pic (info)
               && (type == R_RISCV_PCREL_HI20
                   || type == R_RISCV_PCREL_LO12_I
                   || type == R_RISCV_PCREL_LO12_S))
@@ -4770,7 +4850,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
                 libraries can not happen currently.  Once we support the
                 auipc relaxations when creating shared libraries, then we will
                 need the more rigorous checking for this optimization.  */
-             undefined_weak = TRUE;
+             undefined_weak = true;
            }
 
          /* This line has to match the check in riscv_elf_relocate_section
@@ -4842,12 +4922,15 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
        goto fail;
     }
 
-  ret = TRUE;
+  ret = true;
 
  fail:
   if (relocs != data->relocs)
     free (relocs);
-  riscv_free_pcgp_relocs(&pcgp_relocs, abfd, sec);
+  riscv_free_pcgp_relocs (&pcgp_relocs, abfd, sec);
+
+  if (*again)
+    htab->restart_relax = true;
 
   return ret;
 }
@@ -4862,6 +4945,8 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
 # define PRPSINFO_OFFSET_PR_PID                16
 # define PRPSINFO_OFFSET_PR_FNAME      32
 # define PRPSINFO_OFFSET_PR_PSARGS     48
+# define PRPSINFO_PR_FNAME_LENGTH      16
+# define PRPSINFO_PR_PSARGS_LENGTH     80
 #else
 # define PRSTATUS_SIZE                 376
 # define PRSTATUS_OFFSET_PR_CURSIG     12
@@ -4872,19 +4957,94 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
 # define PRPSINFO_OFFSET_PR_PID                24
 # define PRPSINFO_OFFSET_PR_FNAME      40
 # define PRPSINFO_OFFSET_PR_PSARGS     56
+# define PRPSINFO_PR_FNAME_LENGTH      16
+# define PRPSINFO_PR_PSARGS_LENGTH     80
 #endif
 
+/* Write PRSTATUS and PRPSINFO note into core file.  This will be called
+   before the generic code in elf.c.  By checking the compiler defines we
+   only perform any action here if the generic code would otherwise not be
+   able to help us.  The intention is that bare metal core dumps (where the
+   prstatus_t and/or prpsinfo_t might not be available) will use this code,
+   while non bare metal tools will use the generic elf code.  */
+
+static char *
+riscv_write_core_note (bfd *abfd ATTRIBUTE_UNUSED,
+                       char *buf ATTRIBUTE_UNUSED,
+                       int *bufsiz ATTRIBUTE_UNUSED,
+                       int note_type ATTRIBUTE_UNUSED, ...)
+{
+  switch (note_type)
+    {
+    default:
+      return NULL;
+
+#if !defined (HAVE_PRPSINFO_T)
+    case NT_PRPSINFO:
+      {
+       char data[PRPSINFO_SIZE] ATTRIBUTE_NONSTRING;
+       va_list ap;
+
+       va_start (ap, note_type);
+       memset (data, 0, sizeof (data));
+       strncpy (data + PRPSINFO_OFFSET_PR_FNAME, va_arg (ap, const char *),
+                 PRPSINFO_PR_FNAME_LENGTH);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+       DIAGNOSTIC_PUSH;
+       /* GCC 8.0 and 8.1 warn about 80 equals destination size with
+          -Wstringop-truncation:
+          https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
+        */
+       DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
+#endif
+       strncpy (data + PRPSINFO_OFFSET_PR_PSARGS, va_arg (ap, const char *),
+                 PRPSINFO_PR_PSARGS_LENGTH);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+       DIAGNOSTIC_POP;
+#endif
+       va_end (ap);
+       return elfcore_write_note (abfd, buf, bufsiz,
+                                  "CORE", note_type, data, sizeof (data));
+      }
+#endif /* !HAVE_PRPSINFO_T */
+
+#if !defined (HAVE_PRSTATUS_T)
+    case NT_PRSTATUS:
+      {
+        char data[PRSTATUS_SIZE];
+        va_list ap;
+        long pid;
+        int cursig;
+        const void *greg;
+
+        va_start (ap, note_type);
+        memset (data, 0, sizeof(data));
+        pid = va_arg (ap, long);
+        bfd_put_32 (abfd, pid, data + PRSTATUS_OFFSET_PR_PID);
+        cursig = va_arg (ap, int);
+        bfd_put_16 (abfd, cursig, data + PRSTATUS_OFFSET_PR_CURSIG);
+        greg = va_arg (ap, const void *);
+        memcpy (data + PRSTATUS_OFFSET_PR_REG, greg,
+                PRSTATUS_SIZE - PRSTATUS_OFFSET_PR_REG - ARCH_SIZE / 8);
+        va_end (ap);
+        return elfcore_write_note (abfd, buf, bufsiz,
+                                   "CORE", note_type, data, sizeof (data));
+      }
+#endif /* !HAVE_PRSTATUS_T */
+    }
+}
+
 /* Support for core dump NOTE sections.  */
 
-static bfd_boolean
+static bool
 riscv_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   switch (note->descsz)
     {
       default:
-       return FALSE;
+       return false;
 
-      case PRSTATUS_SIZE:  /* sizeof(struct elf_prstatus) on Linux/RISC-V.  */
+      case PRSTATUS_SIZE: /* sizeof(struct elf_prstatus) on Linux/RISC-V.  */
        /* pr_cursig */
        elf_tdata (abfd)->core->signal
          = bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
@@ -4900,13 +5060,13 @@ riscv_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
                                          note->descpos + PRSTATUS_OFFSET_PR_REG);
 }
 
-static bfd_boolean
+static bool
 riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   switch (note->descsz)
     {
       default:
-       return FALSE;
+       return false;
 
       case PRPSINFO_SIZE: /* sizeof(struct elf_prpsinfo) on Linux/RISC-V.  */
        /* pr_pid */
@@ -4915,11 +5075,13 @@ riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
        /* pr_fname */
        elf_tdata (abfd)->core->program = _bfd_elfcore_strndup
-         (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME, 16);
+         (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
+           PRPSINFO_PR_FNAME_LENGTH);
 
        /* pr_psargs */
        elf_tdata (abfd)->core->command = _bfd_elfcore_strndup
-         (abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS, 80);
+         (abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS,
+           PRPSINFO_PR_PSARGS_LENGTH);
        break;
     }
 
@@ -4935,20 +5097,22 @@ riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
       command[n - 1] = '\0';
   }
 
-  return TRUE;
+  return true;
 }
 
 /* Set the right mach type.  */
-static bfd_boolean
+
+static bool
 riscv_elf_object_p (bfd *abfd)
 {
   /* There are only two mach types in RISCV currently.  */
-  if (strcmp (abfd->xvec->name, "elf32-littleriscv") == 0)
+  if (strcmp (abfd->xvec->name, "elf32-littleriscv") == 0
+      || strcmp (abfd->xvec->name, "elf32-bigriscv") == 0)
     bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv32);
   else
     bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv64);
 
-  return TRUE;
+  return true;
 }
 
 /* Determine whether an object attribute tag takes an integer, a
@@ -4960,55 +5124,69 @@ riscv_elf_obj_attrs_arg_type (int tag)
   return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL;
 }
 
-#define TARGET_LITTLE_SYM              riscv_elfNN_vec
-#define TARGET_LITTLE_NAME             "elfNN-littleriscv"
+/* PR27584, Omit local and empty symbols since they usually generated
+   for pcrel relocations.  */
 
-#define elf_backend_reloc_type_class        riscv_reloc_type_class
+static bool
+riscv_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
+{
+  return (!strcmp (sym->name, "")
+         || _bfd_elf_is_local_label_name (abfd, sym->name));
+}
 
-#define bfd_elfNN_bfd_reloc_name_lookup             riscv_reloc_name_lookup
-#define bfd_elfNN_bfd_link_hash_table_create riscv_elf_link_hash_table_create
-#define bfd_elfNN_bfd_reloc_type_lookup             riscv_reloc_type_lookup
+#define TARGET_LITTLE_SYM                      riscv_elfNN_vec
+#define TARGET_LITTLE_NAME                     "elfNN-littleriscv"
+#define TARGET_BIG_SYM                         riscv_elfNN_be_vec
+#define TARGET_BIG_NAME                                "elfNN-bigriscv"
+
+#define elf_backend_reloc_type_class           riscv_reloc_type_class
+
+#define bfd_elfNN_bfd_reloc_name_lookup                riscv_reloc_name_lookup
+#define bfd_elfNN_bfd_link_hash_table_create   riscv_elf_link_hash_table_create
+#define bfd_elfNN_bfd_reloc_type_lookup                riscv_reloc_type_lookup
 #define bfd_elfNN_bfd_merge_private_bfd_data \
   _bfd_riscv_elf_merge_private_bfd_data
-
-#define elf_backend_copy_indirect_symbol     riscv_elf_copy_indirect_symbol
-#define elf_backend_create_dynamic_sections  riscv_elf_create_dynamic_sections
-#define elf_backend_check_relocs            riscv_elf_check_relocs
-#define elf_backend_adjust_dynamic_symbol    riscv_elf_adjust_dynamic_symbol
-#define elf_backend_size_dynamic_sections    riscv_elf_size_dynamic_sections
-#define elf_backend_relocate_section        riscv_elf_relocate_section
-#define elf_backend_finish_dynamic_symbol    riscv_elf_finish_dynamic_symbol
-#define elf_backend_finish_dynamic_sections  riscv_elf_finish_dynamic_sections
-#define elf_backend_gc_mark_hook            riscv_elf_gc_mark_hook
-#define elf_backend_plt_sym_val                     riscv_elf_plt_sym_val
-#define elf_backend_grok_prstatus           riscv_elf_grok_prstatus
-#define elf_backend_grok_psinfo                     riscv_elf_grok_psinfo
-#define elf_backend_object_p                riscv_elf_object_p
-#define elf_info_to_howto_rel               NULL
-#define elf_info_to_howto                   riscv_info_to_howto_rela
-#define bfd_elfNN_bfd_relax_section         _bfd_riscv_relax_section
-#define bfd_elfNN_mkobject                  elfNN_riscv_mkobject
-
-#define elf_backend_init_index_section      _bfd_elf_init_1_index_section
-
-#define elf_backend_can_gc_sections    1
-#define elf_backend_can_refcount       1
-#define elf_backend_want_got_plt       1
-#define elf_backend_plt_readonly       1
-#define elf_backend_plt_alignment      4
-#define elf_backend_want_plt_sym       1
-#define elf_backend_got_header_size    (ARCH_SIZE / 8)
-#define elf_backend_want_dynrelro      1
-#define elf_backend_rela_normal                1
-#define elf_backend_default_execstack  0
+#define bfd_elfNN_bfd_is_target_special_symbol riscv_elf_is_target_special_symbol
+
+#define elf_backend_copy_indirect_symbol       riscv_elf_copy_indirect_symbol
+#define elf_backend_create_dynamic_sections    riscv_elf_create_dynamic_sections
+#define elf_backend_check_relocs               riscv_elf_check_relocs
+#define elf_backend_adjust_dynamic_symbol      riscv_elf_adjust_dynamic_symbol
+#define elf_backend_size_dynamic_sections      riscv_elf_size_dynamic_sections
+#define elf_backend_relocate_section           riscv_elf_relocate_section
+#define elf_backend_finish_dynamic_symbol      riscv_elf_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections    riscv_elf_finish_dynamic_sections
+#define elf_backend_gc_mark_hook               riscv_elf_gc_mark_hook
+#define elf_backend_plt_sym_val                        riscv_elf_plt_sym_val
+#define elf_backend_grok_prstatus              riscv_elf_grok_prstatus
+#define elf_backend_grok_psinfo                        riscv_elf_grok_psinfo
+#define elf_backend_object_p                   riscv_elf_object_p
+#define elf_backend_write_core_note            riscv_write_core_note
+#define elf_info_to_howto_rel                  NULL
+#define elf_info_to_howto                      riscv_info_to_howto_rela
+#define bfd_elfNN_bfd_relax_section            _bfd_riscv_relax_section
+#define bfd_elfNN_mkobject                     elfNN_riscv_mkobject
+
+#define elf_backend_init_index_section         _bfd_elf_init_1_index_section
+
+#define elf_backend_can_gc_sections            1
+#define elf_backend_can_refcount               1
+#define elf_backend_want_got_plt               1
+#define elf_backend_plt_readonly               1
+#define elf_backend_plt_alignment              4
+#define elf_backend_want_plt_sym               1
+#define elf_backend_got_header_size            (ARCH_SIZE / 8)
+#define elf_backend_want_dynrelro              1
+#define elf_backend_rela_normal                        1
+#define elf_backend_default_execstack          0
 
 #undef  elf_backend_obj_attrs_vendor
-#define elf_backend_obj_attrs_vendor            "riscv"
+#define elf_backend_obj_attrs_vendor           "riscv"
 #undef  elf_backend_obj_attrs_arg_type
-#define elf_backend_obj_attrs_arg_type          riscv_elf_obj_attrs_arg_type
+#define elf_backend_obj_attrs_arg_type         riscv_elf_obj_attrs_arg_type
 #undef  elf_backend_obj_attrs_section_type
-#define elf_backend_obj_attrs_section_type      SHT_RISCV_ATTRIBUTES
+#define elf_backend_obj_attrs_section_type     SHT_RISCV_ATTRIBUTES
 #undef  elf_backend_obj_attrs_section
-#define elf_backend_obj_attrs_section           ".riscv.attributes"
+#define elf_backend_obj_attrs_section          ".riscv.attributes"
 
 #include "elfNN-target.h"
This page took 0.135898 seconds and 4 git commands to generate.