You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/02/07 23:01:15 UTC

[incubator-nuttx] branch pr220 updated: ELF64 support (#220)

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch pr220
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/pr220 by this push:
     new 468ea84  ELF64 support (#220)
468ea84 is described below

commit 468ea847930c4fad1e9d888e94ec3b6c650c53d1
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Sat Feb 8 08:01:06 2020 +0900

    ELF64 support (#220)
    
    * include: Introduce elf64.h and elf.h
    
    Added elf64.h for 64bit ELF support and moved common definitions
    from elf32.h to elf.h. Also introduced Elf_xxx to be used in
    common libraries such as binfmt.
    
    * binfmt, include, modlib, module: Add support for ELF64
    
    Elf_xxx must be used instead of Elf32_xxx to support ELF64.
    To use ELF64, CONFIG_ELF_64BIT must be enabled.
    
    * binfmt, modlib: Add support for relocate address
    
    * arch: risc-v: Add include/elf.h
    
    * libs: machine: Add risc-v related files.
    
    NOTE: Currently only supports ELF64
    
    * boards: maix-bit: Add elf and posix_spawn configurations
    
    * boards: maix-bit: Add support for module configuration
---
 arch/risc-v/include/elf.h                          |  86 ++++
 binfmt/elf.c                                       |   2 +-
 binfmt/libelf/Kconfig                              |   6 +
 binfmt/libelf/libelf.h                             |   6 +-
 binfmt/libelf/libelf_bind.c                        | 260 +++++++++++--
 binfmt/libelf/libelf_ctors.c                       |   2 +-
 binfmt/libelf/libelf_dtors.c                       |   2 +-
 binfmt/libelf/libelf_init.c                        |   4 +-
 binfmt/libelf/libelf_load.c                        |   4 +-
 binfmt/libelf/libelf_sections.c                    |   8 +-
 binfmt/libelf/libelf_symbols.c                     |  16 +-
 binfmt/libelf/libelf_verify.c                      |   2 +-
 boards/risc-v/k210/maix-bit/configs/elf/defconfig  |  59 +++
 .../risc-v/k210/maix-bit/configs/module/defconfig  |  61 +++
 .../k210/maix-bit/configs/posix_spawn/defconfig    |  57 +++
 boards/risc-v/k210/maix-bit/scripts/Make.defs      |  27 ++
 boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld     | 115 ++++++
 include/{elf32.h => elf.h}                         | 206 ++--------
 include/elf32.h                                    | 193 +--------
 include/elf64.h                                    | 157 ++++++++
 include/nuttx/binfmt/elf.h                         |   7 +-
 include/nuttx/elf.h                                |  12 +-
 include/nuttx/lib/modlib.h                         |   6 +-
 libs/libc/dlfcn/lib_dlopen.c                       |   2 +-
 libs/libc/machine/Kconfig                          |   3 +
 libs/libc/machine/Make.defs                        |   3 +
 libs/libc/machine/risc-v/Kconfig                   |   9 +
 libs/libc/machine/risc-v/Make.defs                 |  23 ++
 libs/libc/machine/risc-v/rv64/Kconfig              |   4 +
 libs/libc/machine/risc-v/rv64/Make.defs            |  28 ++
 libs/libc/machine/risc-v/rv64/arch_elf.c           | 432 +++++++++++++++++++++
 libs/libc/modlib/modlib.h                          |   6 +-
 libs/libc/modlib/modlib_bind.c                     | 254 ++++++++++--
 libs/libc/modlib/modlib_init.c                     |   4 +-
 libs/libc/modlib/modlib_load.c                     |   4 +-
 libs/libc/modlib/modlib_sections.c                 |   8 +-
 libs/libc/modlib/modlib_symbols.c                  |  16 +-
 libs/libc/modlib/modlib_verify.c                   |   2 +-
 libs/libxx/libxx__gnu_unwind_find_exidx.cxx        |   2 +-
 sched/module/mod_insmod.c                          |   2 +-
 40 files changed, 1643 insertions(+), 457 deletions(-)

diff --git a/arch/risc-v/include/elf.h b/arch/risc-v/include/elf.h
new file mode 100644
index 0000000..6fd222b
--- /dev/null
+++ b/arch/risc-v/include/elf.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * arch/risc-v/include/elf.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_INCLUDE_ELF_H
+#define __ARCH_RISCV_INCLUDE_ELF_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md */
+
+#define R_RISCV_NONE           0
+#define R_RISCV_32             1
+#define R_RISCV_64             2
+#define R_RISCV_RELATIVE       3
+#define R_RISCV_COPY           4
+#define R_RISCV_JUMP_SLOT      5
+#define R_RISCV_TLS_DTPMOD32   6
+#define R_RISCV_TLS_DTPMOD64   7
+#define R_RISCV_TLS_DTPREL32   8
+#define R_RISCV_TLS_DTPREL64   9
+#define R_RISCV_TLS_TPREL32   10
+#define R_RISCV_TLS_TPREL64   11
+
+#define R_RISCV_BRANCH        16
+#define R_RISCV_JAL           17
+#define R_RISCV_CALL          18
+#define R_RISCV_CALL_PLT      19
+#define R_RISCV_GOT_HI20      20
+#define R_RISCV_TLS_GOT_HI20  21
+#define R_RISCV_TLS_GD_HI20   22
+#define R_RISCV_PCREL_HI20    23
+#define R_RISCV_PCREL_LO12_I  24
+#define R_RISCV_PCREL_LO12_S  25
+#define R_RISCV_HI20          26
+#define R_RISCV_LO12_I        27
+#define R_RISCV_LO12_S        28
+#define R_RISCV_TPREL_HI20    29
+#define R_RISCV_TPREL_LO12_I  30
+#define R_RISCV_TPREL_LO12_S  31
+#define R_RISCV_TPREL_ADD     32
+#define R_RISCV_ADD8          33
+#define R_RISCV_ADD16         34
+#define R_RISCV_ADD32         35
+#define R_RISCV_ADD64         36
+#define R_RISCV_SUB8          37
+#define R_RISCV_SUB16         38
+#define R_RISCV_SUB32         39
+#define R_RISCV_SUB64         40
+#define R_RISCV_GNU_VTINHERIT 41
+#define R_RISCV_GNU_VTENTRY   42
+#define R_RISCV_ALIGN         43
+#define R_RISCV_RVC_BRANCH    44
+#define R_RISCV_RVC_JUMP      45
+#define R_RISCV_RVC_LUI       46
+#define R_RISCV_GPREL_I       47
+#define R_RISCV_GPREL_S       48
+#define R_RISCV_TPREL_I       49
+#define R_RISCV_TPREL_S       50
+#define R_RISCV_RELAX         51
+#define R_RISCV_SUB6          52
+#define R_RISCV_SET6          53
+#define R_RISCV_SET8          54
+#define R_RISCV_SET16         55
+#define R_RISCV_SET32         56
+#define R_RISCV_32_PCREL      57
+
+#endif /* __ARCH_RISCV_INCLUDE_ELF_H */
diff --git a/binfmt/elf.c b/binfmt/elf.c
index 7177d27..66632d7 100644
--- a/binfmt/elf.c
+++ b/binfmt/elf.c
@@ -152,7 +152,7 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
     {
       for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
         {
-          FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+          FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
           binfo("Sections %d:\n", i);
           binfo("  sh_name:      %08x\n", shdr->sh_name);
           binfo("  sh_type:      %08x\n", shdr->sh_type);
diff --git a/binfmt/libelf/Kconfig b/binfmt/libelf/Kconfig
index 5f2f292..1546d2b 100644
--- a/binfmt/libelf/Kconfig
+++ b/binfmt/libelf/Kconfig
@@ -3,6 +3,12 @@
 # see the file kconfig-language.txt in the NuttX tools repository.
 #
 
+config ELF_64BIT
+	bool "64bit ELF support"
+	default n
+	---help---
+		This option is used to load 64bit ELF files
+
 config ELF_ALIGN_LOG2
 	int "Log2 Section Alignment"
 	default 2
diff --git a/binfmt/libelf/libelf.h b/binfmt/libelf/libelf.h
index 350b3c5..0c2b712 100644
--- a/binfmt/libelf/libelf.h
+++ b/binfmt/libelf/libelf.h
@@ -64,7 +64,7 @@
  *
  ****************************************************************************/
 
-int elf_verifyheader(FAR const Elf32_Ehdr *header);
+int elf_verifyheader(FAR const Elf_Ehdr *header);
 
 /****************************************************************************
  * Name: elf_read
@@ -150,7 +150,7 @@ int elf_findsymtab(FAR struct elf_loadinfo_s *loadinfo);
  ****************************************************************************/
 
 int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
-                FAR Elf32_Sym *sym);
+                FAR Elf_Sym *sym);
 
 /****************************************************************************
  * Name: elf_symvalue
@@ -177,7 +177,7 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
  *
  ****************************************************************************/
 
-int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
+int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_Sym *sym,
                  FAR const struct symtab_s *exports, int nexports);
 
 /****************************************************************************
diff --git a/binfmt/libelf/libelf_bind.c b/binfmt/libelf/libelf_bind.c
index 1fb1ab5..47330f0 100644
--- a/binfmt/libelf/libelf_bind.c
+++ b/binfmt/libelf/libelf_bind.c
@@ -74,14 +74,14 @@
  * Private Types
  ****************************************************************************/
 
-struct elf32_symcache_s
+struct elf_symcache_s
 {
   dq_entry_t    entry;
-  Elf32_Sym     sym;
+  Elf_Sym       sym;
   int           idx;
 };
 
-typedef struct elf32_symcache_s elf32_symcache_t;
+typedef struct elf_symcache_s elf_symcache_t;
 
 /****************************************************************************
  * Private Data
@@ -95,13 +95,13 @@ typedef struct elf32_symcache_s elf32_symcache_t;
  * Name: elf_readrels
  *
  * Description:
- *   Read the (ELF32_Rel structure * buffer count) into memory.
+ *   Read the (ELF_Rel structure * buffer count) into memory.
  *
  ****************************************************************************/
 
 static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo,
-                               FAR const Elf32_Shdr *relsec,
-                               int index, FAR Elf32_Rel *rels,
+                               FAR const Elf_Shdr *relsec,
+                               int index, FAR Elf_Rel *rels,
                                int count)
 {
   off_t offset;
@@ -109,7 +109,7 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo,
 
   /* Verify that the symbol table index lies within symbol table */
 
-  if (index < 0 || index > (relsec->sh_size / sizeof(Elf32_Rel)))
+  if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rel)))
     {
       berr("Bad relocation symbol index: %d\n", index);
       return -EINVAL;
@@ -117,8 +117,9 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo,
 
   /* Get the file offset to the symbol table entry */
 
-  offset = sizeof(Elf32_Rel) * index;
-  size   = sizeof(Elf32_Rel) * count;
+  offset = sizeof(Elf_Rel) * index;
+  size   = sizeof(Elf_Rel) * count;
+
   if (offset + size > relsec->sh_size)
     {
       size = relsec->sh_size - offset;
@@ -131,6 +132,46 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo,
 }
 
 /****************************************************************************
+ * Name: elf_readrelas
+ *
+ * Description:
+ *   Read the (ELF_Rela structure * buffer count) into memory.
+ *
+ ****************************************************************************/
+
+static inline int elf_readrelas(FAR struct elf_loadinfo_s *loadinfo,
+                                FAR const Elf_Shdr *relsec,
+                                int index, FAR Elf_Rela *relas,
+                                int count)
+{
+  off_t offset;
+  int size;
+
+  /* Verify that the symbol table index lies within symbol table */
+
+  if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rela)))
+    {
+      berr("Bad relocation symbol index: %d\n", index);
+      return -EINVAL;
+    }
+
+  /* Get the file offset to the symbol table entry */
+
+  offset = sizeof(Elf_Rela) * index;
+  size   = sizeof(Elf_Rela) * count;
+
+  if (offset + size > relsec->sh_size)
+    {
+      size = relsec->sh_size - offset;
+    }
+
+  /* And, finally, read the symbol table entry into memory */
+
+  return elf_read(loadinfo, (FAR uint8_t *)relas, size,
+                  relsec->sh_offset + offset);
+}
+
+/****************************************************************************
  * Name: elf_relocate and elf_relocateadd
  *
  * Description:
@@ -146,12 +187,12 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
                         FAR const struct symtab_s *exports, int nexports)
 
 {
-  FAR Elf32_Shdr       *relsec = &loadinfo->shdr[relidx];
-  FAR Elf32_Shdr       *dstsec = &loadinfo->shdr[relsec->sh_info];
-  FAR Elf32_Rel        *rels;
-  FAR Elf32_Rel        *rel;
-  FAR elf32_symcache_t *cache;
-  FAR Elf32_Sym        *sym;
+  FAR Elf_Shdr         *relsec = &loadinfo->shdr[relidx];
+  FAR Elf_Shdr         *dstsec = &loadinfo->shdr[relsec->sh_info];
+  FAR Elf_Rel          *rels;
+  FAR Elf_Rel          *rel;
+  FAR elf_symcache_t   *cache;
+  FAR Elf_Sym          *sym;
   FAR dq_entry_t       *e;
   dq_queue_t            q;
   uintptr_t             addr;
@@ -160,7 +201,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
   int                   i;
   int                   j;
 
-  rels = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf32_Rel));
+  rels = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rel));
   if (rels == NULL)
     {
       berr("Failed to allocate memory for elf relocation\n");
@@ -176,7 +217,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
 
   ret = OK;
 
-  for (i = j = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++)
+  for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rel); i++)
     {
       /* Read the relocation entry into memory */
 
@@ -198,14 +239,14 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
        * in a bit-field within the r_info element.
        */
 
-      symidx = ELF32_R_SYM(rel->r_info);
+      symidx = ELF_R_SYM(rel->r_info);
 
       /* First try the cache */
 
       sym = NULL;
       for (e = dq_peek(&q); e; e = dq_next(e))
         {
-          cache = (FAR elf32_symcache_t *)e;
+          cache = (FAR elf_symcache_t *)e;
           if (cache->idx == symidx)
             {
               dq_rem(&cache->entry, &q);
@@ -223,7 +264,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
         {
           if (j < CONFIG_ELF_SYMBOL_CACHECOUNT)
             {
-              cache = kmm_malloc(sizeof(elf32_symcache_t));
+              cache = kmm_malloc(sizeof(elf_symcache_t));
               if (!cache)
                 {
                   berr("Failed to allocate memory for elf symbols\n");
@@ -235,7 +276,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
             }
           else
             {
-              cache = (FAR elf32_symcache_t *)dq_remlast(&q);
+              cache = (FAR elf_symcache_t *)dq_remlast(&q);
             }
 
           sym = &cache->sym;
@@ -326,8 +367,181 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
 static int elf_relocateadd(FAR struct elf_loadinfo_s *loadinfo, int relidx,
                            FAR const struct symtab_s *exports, int nexports)
 {
-  berr("Not implemented\n");
-  return -ENOSYS;
+  FAR Elf_Shdr         *relsec = &loadinfo->shdr[relidx];
+  FAR Elf_Shdr         *dstsec = &loadinfo->shdr[relsec->sh_info];
+  FAR Elf_Rela         *relas;
+  FAR Elf_Rela         *rela;
+  FAR elf_symcache_t   *cache;
+  FAR Elf_Sym          *sym;
+  FAR dq_entry_t       *e;
+  dq_queue_t            q;
+  uintptr_t             addr;
+  int                   symidx;
+  int                   ret;
+  int                   i;
+  int                   j;
+
+  relas = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rela));
+  if (relas == NULL)
+    {
+      berr("Failed to allocate memory for elf relocation\n");
+      return -ENOMEM;
+    }
+
+  dq_init(&q);
+
+  /* Examine each relocation in the section.  'relsec' is the section
+   * containing the relations.  'dstsec' is the section containing the data
+   * to be relocated.
+   */
+
+  ret = OK;
+
+  for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rela); i++)
+    {
+      /* Read the relocation entry into memory */
+
+      rela = &relas[i % CONFIG_ELF_RELOCATION_BUFFERCOUNT];
+
+      if (!(i % CONFIG_ELF_RELOCATION_BUFFERCOUNT))
+        {
+          ret = elf_readrelas(loadinfo, relsec, i, relas,
+                              CONFIG_ELF_RELOCATION_BUFFERCOUNT);
+          if (ret < 0)
+            {
+              berr("Section %d reloc %d: Failed to read relocation entry: %d\n",
+                    relidx, i, ret);
+              break;
+            }
+        }
+
+      /* Get the symbol table index for the relocation.  This is contained
+       * in a bit-field within the r_info element.
+       */
+
+      symidx = ELF_R_SYM(rela->r_info);
+
+      /* First try the cache */
+
+      sym = NULL;
+      for (e = dq_peek(&q); e; e = dq_next(e))
+        {
+          cache = (FAR elf_symcache_t *)e;
+          if (cache->idx == symidx)
+            {
+              dq_rem(&cache->entry, &q);
+              dq_addfirst(&cache->entry, &q);
+              sym = &cache->sym;
+              break;
+            }
+        }
+
+      /* If the symbol was not found in the cache, we will need to read the
+       * symbol from the file.
+       */
+
+      if (sym == NULL)
+        {
+          if (j < CONFIG_ELF_SYMBOL_CACHECOUNT)
+            {
+              cache = kmm_malloc(sizeof(elf_symcache_t));
+              if (!cache)
+                {
+                  berr("Failed to allocate memory for elf symbols\n");
+                  ret = -ENOMEM;
+                  break;
+                }
+
+              j++;
+            }
+          else
+            {
+              cache = (FAR elf_symcache_t *)dq_remlast(&q);
+            }
+
+          sym = &cache->sym;
+
+          /* Read the symbol table entry into memory */
+
+          ret = elf_readsym(loadinfo, symidx, sym);
+          if (ret < 0)
+            {
+              berr("Section %d reloc %d: Failed to read symbol[%d]: %d\n",
+                   relidx, i, symidx, ret);
+              kmm_free(cache);
+              break;
+            }
+
+          /* Get the value of the symbol (in sym.st_value) */
+
+          ret = elf_symvalue(loadinfo, sym, exports, nexports);
+          if (ret < 0)
+            {
+              /* The special error -ESRCH is returned only in one condition:  The
+               * symbol has no name.
+               *
+               * There are a few relocations for a few architectures that do
+               * no depend upon a named symbol.  We don't know if that is the
+               * case here, but we will use a NULL symbol pointer to indicate
+               * that case to up_relocate().  That function can then do what
+               * is best.
+               */
+
+              if (ret == -ESRCH)
+                {
+                  berr("Section %d reloc %d: Undefined symbol[%d] has no name: %d\n",
+                      relidx, i, symidx, ret);
+                }
+              else
+                {
+                  berr("Section %d reloc %d: Failed to get value of symbol[%d]: %d\n",
+                       relidx, i, symidx, ret);
+                  kmm_free(cache);
+                  break;
+                }
+            }
+
+          cache->idx = symidx;
+          dq_addfirst(&cache->entry, &q);
+        }
+
+      if (sym->st_shndx == SHN_UNDEF && sym->st_name == 0)
+        {
+          sym = NULL;
+        }
+
+      /* Calculate the relocation address. */
+
+      if (rela->r_offset < 0 ||
+          rela->r_offset > dstsec->sh_size)
+        {
+          berr("Section %d reloc %d: Relocation address out of range, "
+               "offset %d size %d\n",
+               relidx, i, rela->r_offset, dstsec->sh_size);
+          ret = -EINVAL;
+          break;
+        }
+
+      addr = dstsec->sh_addr + rela->r_offset;
+
+      /* Now perform the architecture-specific relocation */
+
+      ret = up_relocateadd(rela, sym, addr);
+      if (ret < 0)
+        {
+          berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", relidx, i, ret);
+          break;
+        }
+    }
+
+  kmm_free(relas);
+  while ((e = dq_peek(&q)))
+    {
+      dq_rem(e, &q);
+      kmm_free(e);
+    }
+
+  return ret;
 }
 
 /****************************************************************************
diff --git a/binfmt/libelf/libelf_ctors.c b/binfmt/libelf/libelf_ctors.c
index 6994602..3715e3c 100644
--- a/binfmt/libelf/libelf_ctors.c
+++ b/binfmt/libelf/libelf_ctors.c
@@ -88,7 +88,7 @@
 
 int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
 {
-  FAR Elf32_Shdr *shdr;
+  FAR Elf_Shdr *shdr;
   size_t ctorsize;
   int ctoridx;
   int ret;
diff --git a/binfmt/libelf/libelf_dtors.c b/binfmt/libelf/libelf_dtors.c
index 3bfa00e..62cb343 100644
--- a/binfmt/libelf/libelf_dtors.c
+++ b/binfmt/libelf/libelf_dtors.c
@@ -88,7 +88,7 @@
 
 int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
 {
-  FAR Elf32_Shdr *shdr;
+  FAR Elf_Shdr *shdr;
   size_t dtorsize;
   int dtoridx;
   int ret;
diff --git a/binfmt/libelf/libelf_init.c b/binfmt/libelf/libelf_init.c
index 287aa81..99fa46b 100644
--- a/binfmt/libelf/libelf_init.c
+++ b/binfmt/libelf/libelf_init.c
@@ -173,7 +173,7 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
   /* Read the ELF ehdr from offset 0 */
 
   ret = elf_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr,
-                 sizeof(Elf32_Ehdr), 0);
+                 sizeof(Elf_Ehdr), 0);
   if (ret < 0)
     {
       berr("Failed to read ELF header: %d\n", ret);
@@ -182,7 +182,7 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
     }
 
   elf_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr,
-                 sizeof(Elf32_Ehdr));
+                 sizeof(Elf_Ehdr));
 
   /* Verify the ELF header */
 
diff --git a/binfmt/libelf/libelf_load.c b/binfmt/libelf/libelf_load.c
index 3deff9d..a51416a 100644
--- a/binfmt/libelf/libelf_load.c
+++ b/binfmt/libelf/libelf_load.c
@@ -106,7 +106,7 @@ static void elf_elfsize(struct elf_loadinfo_s *loadinfo)
 
   for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
     {
-      FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+      FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
 
       /* SHF_ALLOC indicates that the section requires memory during
        * execution.
@@ -164,7 +164,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
 
   for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
     {
-      FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+      FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
 
       /* SHF_ALLOC indicates that the section requires memory during
        * execution.
diff --git a/binfmt/libelf/libelf_sections.c b/binfmt/libelf/libelf_sections.c
index 6f58b4a..8dd4930 100644
--- a/binfmt/libelf/libelf_sections.c
+++ b/binfmt/libelf/libelf_sections.c
@@ -75,9 +75,9 @@
  ****************************************************************************/
 
 static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
-                               FAR const Elf32_Shdr *shdr)
+                               FAR const Elf_Shdr *shdr)
 {
-  FAR Elf32_Shdr *shstr;
+  FAR Elf_Shdr *shstr;
   FAR uint8_t *buffer;
   off_t  offset;
   size_t readlen;
@@ -210,7 +210,7 @@ int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
 
   /* Allocate memory to hold a working copy of the sector header table */
 
-  loadinfo->shdr = (FAR FAR Elf32_Shdr *)kmm_malloc(shdrsize);
+  loadinfo->shdr = (FAR FAR Elf_Shdr *)kmm_malloc(shdrsize);
   if (!loadinfo->shdr)
     {
       berr("Failed to allocate the section header table. Size: %ld\n",
@@ -249,7 +249,7 @@ int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
 int elf_findsection(FAR struct elf_loadinfo_s *loadinfo,
                     FAR const char *sectname)
 {
-  FAR const Elf32_Shdr *shdr;
+  FAR const Elf_Shdr *shdr;
   int ret;
   int i;
 
diff --git a/binfmt/libelf/libelf_symbols.c b/binfmt/libelf/libelf_symbols.c
index cc435af..16ed06f 100644
--- a/binfmt/libelf/libelf_symbols.c
+++ b/binfmt/libelf/libelf_symbols.c
@@ -78,7 +78,7 @@
  ****************************************************************************/
 
 static int elf_symname(FAR struct elf_loadinfo_s *loadinfo,
-                       FAR const Elf32_Sym *sym)
+                       FAR const Elf_Sym *sym)
 {
   FAR uint8_t *buffer;
   off_t  offset;
@@ -215,14 +215,14 @@ int elf_findsymtab(FAR struct elf_loadinfo_s *loadinfo)
  ****************************************************************************/
 
 int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
-                FAR Elf32_Sym *sym)
+                FAR Elf_Sym *sym)
 {
-  FAR Elf32_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
+  FAR Elf_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
   off_t offset;
 
   /* Verify that the symbol table index lies within symbol table */
 
-  if (index < 0 || index > (symtab->sh_size / sizeof(Elf32_Sym)))
+  if (index < 0 || index > (symtab->sh_size / sizeof(Elf_Sym)))
     {
       berr("Bad relocation symbol index: %d\n", index);
       return -EINVAL;
@@ -230,11 +230,11 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
 
   /* Get the file offset to the symbol table entry */
 
-  offset = symtab->sh_offset + sizeof(Elf32_Sym) * index;
+  offset = symtab->sh_offset + sizeof(Elf_Sym) * index;
 
   /* And, finally, read the symbol table entry into memory */
 
-  return elf_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset);
+  return elf_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf_Sym), offset);
 }
 
 /****************************************************************************
@@ -260,7 +260,7 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
  *
  ****************************************************************************/
 
-int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
+int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_Sym *sym,
                  FAR const struct symtab_s *exports, int nexports)
 {
   FAR const struct symtab_s *symbol;
@@ -324,7 +324,7 @@ int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
               loadinfo->iobuffer, sym->st_value, symbol->sym_value,
               sym->st_value + symbol->sym_value);
 
-        sym->st_value += (Elf32_Word)((uintptr_t)symbol->sym_value);
+        sym->st_value += (Elf_Word)((uintptr_t)symbol->sym_value);
       }
       break;
 
diff --git a/binfmt/libelf/libelf_verify.c b/binfmt/libelf/libelf_verify.c
index d06b6f8..186d212 100644
--- a/binfmt/libelf/libelf_verify.c
+++ b/binfmt/libelf/libelf_verify.c
@@ -84,7 +84,7 @@ static const char g_elfmagic[EI_MAGIC_SIZE] =
  *
  ****************************************************************************/
 
-int elf_verifyheader(FAR const Elf32_Ehdr *ehdr)
+int elf_verifyheader(FAR const Elf_Ehdr *ehdr)
 {
   if (!ehdr)
     {
diff --git a/boards/risc-v/k210/maix-bit/configs/elf/defconfig b/boards/risc-v/k210/maix-bit/configs/elf/defconfig
new file mode 100644
index 0000000..2a63aff
--- /dev/null
+++ b/boards/risc-v/k210/maix-bit/configs/elf/defconfig
@@ -0,0 +1,59 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="maix-bit"
+CONFIG_ARCH_BOARD_MAIX_BIT=y
+CONFIG_ARCH_CHIP="k210"
+CONFIG_ARCH_CHIP_K210=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_APP_SYMTAB=y
+CONFIG_BOARD_LOOPSPERMSEC=46000
+CONFIG_BUILTIN=y
+CONFIG_CXX_NEWLONG=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEV_ZERO=y
+CONFIG_ELF=y
+CONFIG_ELF_64BIT=y
+CONFIG_ELF_ALIGN_LOG2=3
+CONFIG_EXAMPLES_ELF=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_ROMFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_LIB_BOARDCTL=y
+CONFIG_LIB_ENVPATH=y
+CONFIG_MAX_TASKS=64
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_NFILE_STREAMS=8
+CONFIG_PATH_INITIAL="/mnt/romfs"
+CONFIG_PIPES=y
+CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=3072
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PREALLOC_WDOGS=16
+CONFIG_RAM_SIZE=2097152
+CONFIG_RAM_START=0x80400000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=5
+CONFIG_START_MONTH=2
+CONFIG_START_YEAR=2020
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_TASK_NAME_SIZE=20
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USERMAIN_STACKSIZE=3072
+CONFIG_USER_ENTRYPOINT="elf_main"
+CONFIG_WDOG_INTRESERVE=0
diff --git a/boards/risc-v/k210/maix-bit/configs/module/defconfig b/boards/risc-v/k210/maix-bit/configs/module/defconfig
new file mode 100644
index 0000000..1879ac0
--- /dev/null
+++ b/boards/risc-v/k210/maix-bit/configs/module/defconfig
@@ -0,0 +1,61 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="maix-bit"
+CONFIG_ARCH_BOARD_MAIX_BIT=y
+CONFIG_ARCH_CHIP="k210"
+CONFIG_ARCH_CHIP_K210=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_APP_SYMTAB=y
+CONFIG_BOARD_LOOPSPERMSEC=46000
+CONFIG_BUILTIN=y
+CONFIG_CXX_NEWLONG=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEV_ZERO=y
+CONFIG_ELF=y
+CONFIG_ELF_64BIT=y
+CONFIG_ELF_ALIGN_LOG2=3
+CONFIG_EXAMPLES_MODULE=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_ROMFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_EXECFUNCS=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_LIB_BOARDCTL=y
+CONFIG_LIB_ENVPATH=y
+CONFIG_MAX_TASKS=64
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_MODULE=y
+CONFIG_NFILE_STREAMS=8
+CONFIG_PATH_INITIAL="/mnt/romfs"
+CONFIG_PIPES=y
+CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=3072
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PREALLOC_WDOGS=16
+CONFIG_RAM_SIZE=2097152
+CONFIG_RAM_START=0x80400000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=5
+CONFIG_START_MONTH=2
+CONFIG_START_YEAR=2020
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_TASK_NAME_SIZE=20
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USERMAIN_STACKSIZE=3072
+CONFIG_USER_ENTRYPOINT="module_main"
+CONFIG_WDOG_INTRESERVE=0
diff --git a/boards/risc-v/k210/maix-bit/configs/posix_spawn/defconfig b/boards/risc-v/k210/maix-bit/configs/posix_spawn/defconfig
new file mode 100644
index 0000000..974b668
--- /dev/null
+++ b/boards/risc-v/k210/maix-bit/configs/posix_spawn/defconfig
@@ -0,0 +1,57 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="maix-bit"
+CONFIG_ARCH_BOARD_MAIX_BIT=y
+CONFIG_ARCH_CHIP="k210"
+CONFIG_ARCH_CHIP_K210=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_APP_SYMTAB=y
+CONFIG_BOARD_LOOPSPERMSEC=46000
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEV_ZERO=y
+CONFIG_ELF=y
+CONFIG_ELF_64BIT=y
+CONFIG_EXAMPLES_POSIXSPAWN=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_ROMFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_EXECFUNCS=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_LIB_BOARDCTL=y
+CONFIG_LIB_ENVPATH=y
+CONFIG_MAX_TASKS=64
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_NFILE_STREAMS=8
+CONFIG_PATH_INITIAL="/mnt/romfs"
+CONFIG_PIPES=y
+CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PREALLOC_WDOGS=16
+CONFIG_RAM_SIZE=2097152
+CONFIG_RAM_START=0x80400000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=28
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2019
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_TASK_NAME_SIZE=20
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USERMAIN_STACKSIZE=3072
+CONFIG_USER_ENTRYPOINT="posix_spawn_main"
+CONFIG_WDOG_INTRESERVE=0
diff --git a/boards/risc-v/k210/maix-bit/scripts/Make.defs b/boards/risc-v/k210/maix-bit/scripts/Make.defs
index 1ebda61..074a757 100644
--- a/boards/risc-v/k210/maix-bit/scripts/Make.defs
+++ b/boards/risc-v/k210/maix-bit/scripts/Make.defs
@@ -94,10 +94,37 @@ CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
 CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)
 AFLAGS += $(CFLAGS) -D__ASSEMBLY__ $(ASARCHCPUFLAGS)
 
+# NXFLAT module definitions
+
 NXFLATLDFLAGS1 = -r -d -warn-common
 NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections
 LDNXFLATFLAGS = -e main -s 2048
 
+# Loadable module definitions
+
+CMODULEFLAGS = $(CFLAGS)
+
+LDMODULEFLAGS = -r -e module_initialize
+ifeq ($(WINTOOL),y)
+  LDMODULEFLAGS += -T "${shell cygpath -w $(TOPDIR)/libs/libc/modlib/gnu-elf.ld}"
+else
+  LDMODULEFLAGS += -T $(TOPDIR)/libs/libc/modlib/gnu-elf.ld
+endif
+
+# ELF module definitions
+
+CELFFLAGS = $(CFLAGS)
+CXXELFFLAGS = $(CXXFLAGS)
+
+LDELFFLAGS = -r -e main
+ifeq ($(WINTOOL),y)
+  LDELFFLAGS += -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld}"
+else
+  LDELFFLAGS += -T $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld
+endif
+
+# File extensions
+
 ASMEXT = .S
 OBJEXT = .o
 LIBEXT = .a
diff --git a/boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld b/boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld
new file mode 100644
index 0000000..8e24692
--- /dev/null
+++ b/boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld
@@ -0,0 +1,115 @@
+/****************************************************************************
+ * boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+SECTIONS
+{
+  .text 0x00000000 :
+    {
+      _stext = . ;
+      *(.text)
+      *(.text.*)
+      *(.gnu.warning)
+      *(.stub)
+      *(.glue_7)
+      *(.glue_7t)
+      *(.jcr)
+
+      /* C++ support:  The .init and .fini sections contain specific logic
+       * to manage static constructors and destructors.
+       */
+
+      *(.gnu.linkonce.t.*)
+      *(.init)             /* Old ABI */
+      *(.fini)             /* Old ABI */
+      _etext = . ;
+    }
+
+  .rodata :
+    {
+      _srodata = . ;
+      *(.rodata)
+      *(.rodata1)
+      *(.rodata.*)
+      *(.gnu.linkonce.r*)
+      _erodata = . ;
+    }
+
+  .data :
+    {
+      _sdata = . ;
+      *(.data)
+      *(.data1)
+      *(.data.*)
+      *(.gnu.linkonce.d*)
+      . = ALIGN(4);
+      _edata = . ;
+    }
+
+  /* C++ support. For each global and static local C++ object,
+   * GCC creates a small subroutine to construct the object. Pointers
+   * to these routines (not the routines themselves) are stored as
+   * simple, linear arrays in the .ctors section of the object file.
+   * Similarly, pointers to global/static destructor routines are
+   * stored in .dtors.
+   */
+
+  .ctors :
+    {
+      _sctors = . ;
+      *(.ctors)       /* Old ABI:  Unallocated */
+      *(.init_array)  /* New ABI:  Allocated */
+      _edtors = . ;
+    }
+
+  .dtors :
+    {
+      _sdtors = . ;
+      *(.dtors)       /* Old ABI:  Unallocated */
+      *(.fini_array)  /* New ABI:  Allocated */
+      _edtors = . ;
+    }
+
+  .bss :
+    {
+      _sbss = . ;
+      *(.bss)
+      *(.bss.*)
+      *(.sbss)
+      *(.sbss.*)
+      *(.gnu.linkonce.b*)
+      *(COMMON)
+      _ebss = . ;
+    }
+
+    /* Stabs debugging sections.    */
+
+    .stab 0 : { *(.stab) }
+    .stabstr 0 : { *(.stabstr) }
+    .stab.excl 0 : { *(.stab.excl) }
+    .stab.exclstr 0 : { *(.stab.exclstr) }
+    .stab.index 0 : { *(.stab.index) }
+    .stab.indexstr 0 : { *(.stab.indexstr) }
+    .comment 0 : { *(.comment) }
+    .debug_abbrev 0 : { *(.debug_abbrev) }
+    .debug_info 0 : { *(.debug_info) }
+    .debug_line 0 : { *(.debug_line) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+    .debug_aranges 0 : { *(.debug_aranges) }
+}
diff --git a/include/elf32.h b/include/elf.h
similarity index 56%
copy from include/elf32.h
copy to include/elf.h
index e16ae00..d048b69 100644
--- a/include/elf32.h
+++ b/include/elf.h
@@ -1,43 +1,25 @@
 /****************************************************************************
- * include/elf32.h
+ * include/elf.h
  *
- *   Copyright (C) 2012 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
  *
- * Reference: System V Application Binary Interface, Edition 4.1, March 18,
- * 1997, The Santa Cruz Operation, Inc.
+ *   http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
-#ifndef __INCLUDE_ELF32_H
-#define __INCLUDE_ELF32_H
+#ifndef __INCLUDE_ELF_H
+#define __INCLUDE_ELF_H
 
 /****************************************************************************
  * Included Files
@@ -51,11 +33,7 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Values for Elf32_Ehdr::e_type */
+/* Values for Elf_Ehdr::e_type */
 
 #define ET_NONE           0       /* No file type */
 #define ET_REL            1       /* Relocatable file */
@@ -65,7 +43,7 @@
 #define ET_LOPROC         0xff00  /* Processor-specific */
 #define ET_HIPROC         0xffff  /* Processor-specific */
 
-/* Values for Elf32_Ehdr::e_machine (most of this were not included in the
+/* Values for Elf_Ehdr::e_machine (most of this were not included in the
  * original SCO document but have been gleaned from elsewhere).
  */
 
@@ -86,60 +64,59 @@
 #define EM_ARM             40     /* ARM */
 #define EM_SH              42     /* SuperH */
 #define EM_SPARCV9         43     /* SPARC v9 64-bit */
+#define EM_H8_300          46
 #define EM_IA_64           50     /* HP/Intel IA-64 */
 #define EM_X86_64          62     /* AMD x86-64 */
 #define EM_S390            22     /* IBM S/390 */
 #define EM_CRIS            76     /* Axis Communications 32-bit embedded processor */
 #define EM_V850            87     /* NEC v850 */
 #define EM_M32R            88     /* Renesas M32R */
-#define EM_H8_300          46
+#define EM_RISCV           243    /* RISC-V */
 #define EM_ALPHA           0x9026
 #define EM_CYGNUS_V850     0x9080
 #define EM_CYGNUS_M32R     0x9041
 #define EM_S390_OLD        0xa390
 #define EM_FRV             0x5441
 
-/* Values for Elf32_Ehdr::e_version */
+/* Values for Elf_Ehdr::e_version */
 
 #define EV_NONE            0      /* Invalid version */
 #define EV_CURRENT         1      /* The current version */
 
-/* Ehe ELF identifier */
+/* Table 2. Ehe ELF identifier */
 
 #define EI_MAG0            0      /* File identification */
-#define EI_MAG1            1      /* "  " "            " */
-#define EI_MAG2            2      /* "  " "            " */
-#define EI_MAG3            3      /* "  " "            " */
+#define EI_MAG1            1
+#define EI_MAG2            2
+#define EI_MAG3            3
 #define EI_CLASS           4      /* File class */
 #define EI_DATA            5      /* Data encoding */
 #define EI_VERSION         6      /* File version */
 #define EI_PAD             7      /* Start of padding bytes */
-#define EI_NIDENT          16     /* Size of eident[] */
+#define EI_NIDENT          16     /* Size of e_ident[] */
 
 #define EI_MAGIC_SIZE      4
 #define EI_MAGIC           {0x7f, 'E', 'L', 'F'}
 
-/* Values for EI_CLASS */
+/* Table 3. Values for EI_CLASS */
 
 #define ELFCLASSNONE       0      /* Invalid class */
 #define ELFCLASS32         1      /* 32-bit objects */
 #define ELFCLASS64         2      /* 64-bit objects */
 
-/* Values for EI_DATA */
+/* Table 4. Values for EI_DATA */
 
 #define ELFDATANONE        0     /* Invalid data encoding */
 #define ELFDATA2LSB        1     /* Least significant byte occupying the lowest address */
 #define ELFDATA2MSB        2     /* Most significant byte occupying the lowest address */
 
-/* Figure 4-7: Special Section Indexes */
+/* Table 7: Special Section Indexes */
 
 #define SHN_UNDEF          0
-#define SHN_LORESERVE      0xff00
 #define SHN_LOPROC         0xff00
 #define SHN_HIPROC         0xff1f
 #define SHN_ABS            0xfff1
 #define SHN_COMMON         0xfff2
-#define SHN_HIRESERVE      0xffff
 
 /* Figure 4-9: Section Types, sh_type */
 
@@ -167,13 +144,7 @@
 #define SHF_EXECINSTR      4
 #define SHF_MASKPROC       0xf0000000
 
-/* Definitions for Elf32_Sym::st_info */
-
-#define ELF32_ST_BIND(i)   ((i) >> 4)
-#define ELF32_ST_TYPE(i)   ((i) & 0xf)
-#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf))
-
-/* Figure 4-16: Symbol Binding, ELF32_ST_BIND */
+/* Figure 4-16: Symbol Binding, ELF_ST_BIND */
 
 #define STB_LOCAL          0
 #define STB_GLOBAL         1
@@ -181,7 +152,7 @@
 #define STB_LOPROC         13
 #define STB_HIPROC         15
 
-/* Figure 4-17: Symbol Types, ELF32_ST_TYPE */
+/* Figure 4-17: Symbol Types, ELF_ST_TYPE */
 
 #define STT_NOTYPE         0
 #define STT_OBJECT         1
@@ -191,12 +162,6 @@
 #define STT_LOPROC         13
 #define STT_HIPROC         15
 
-/* Definitions for Elf32_Rel*::r_info */
-
-#define ELF32_R_SYM(i)    ((i) >> 8)
-#define ELF32_R_TYPE(i)   ((i) & 0xff)
-#define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff))
-
 /* Figure 5-2: Segment Types, p_type */
 
 #define PT_NULL            0
@@ -246,107 +211,12 @@
 #define DT_LOPROC          0x70000000 /* d_un=unspecified */
 #define DT_HIPROC          0x7fffffff /* d_un= unspecified */
 
-/****************************************************************************
- * Public Type Definitions
- ****************************************************************************/
+/* NOTE: elf64.h and elf32.h refer EI_NIDENT defined above */
+
+#ifdef CONFIG_ELF_64BIT
+#  include <elf64.h>
+#else
+#  include <elf32.h>
+#endif
 
-/* Figure 4.2: 32-Bit Data Types */
-
-typedef uint32_t  Elf32_Addr;  /* Unsigned program address */
-typedef uint16_t  Elf32_Half;  /* Unsigned medium integer */
-typedef uint32_t  Elf32_Off;   /* Unsigned file offset */
-typedef int32_t   Elf32_Sword; /* Signed large integer */
-typedef uint32_t  Elf32_Word;  /* Unsigned large integer */
-
-/* Figure 4-3: ELF Header */
-
-typedef struct
-{
-  unsigned char e_ident[EI_NIDENT];
-  Elf32_Half    e_type;
-  Elf32_Half    e_machine;
-  Elf32_Word    e_version;
-  Elf32_Addr    e_entry;
-  Elf32_Off     e_phoff;
-  Elf32_Off     e_shoff;
-  Elf32_Word    e_flags;
-  Elf32_Half    e_ehsize;
-  Elf32_Half    e_phentsize;
-  Elf32_Half    e_phnum;
-  Elf32_Half    e_shentsize;
-  Elf32_Half    e_shnum;
-  Elf32_Half    e_shstrndx;
-} Elf32_Ehdr;
-
-/* Figure 4-8: Section Header */
-
-typedef struct
-{
-  Elf32_Word    sh_name;
-  Elf32_Word    sh_type;
-  Elf32_Word    sh_flags;
-  Elf32_Addr    sh_addr;
-  Elf32_Off     sh_offset;
-  Elf32_Word    sh_size;
-  Elf32_Word    sh_link;
-  Elf32_Word    sh_info;
-  Elf32_Word    sh_addralign;
-  Elf32_Word    sh_entsize;
-} Elf32_Shdr;
-
-/* Figure 4-15: Symbol Table Entry */
-
-typedef struct
-{
-  Elf32_Word    st_name;
-  Elf32_Addr    st_value;
-  Elf32_Word    st_size;
-  unsigned char st_info;
-  unsigned char st_other;
-  Elf32_Half    st_shndx;
-} Elf32_Sym;
-
-/* Figure 4-19: Relocation Entries */
-
-typedef struct
-{
-  Elf32_Addr   r_offset;
-  Elf32_Word   r_info;
-} Elf32_Rel;
-
-typedef struct
-{
-  Elf32_Addr   r_offset;
-  Elf32_Word   r_info;
-  Elf32_Sword  r_addend;
-} Elf32_Rela;
-
-/* Figure 5-1: Program Header */
-
-typedef struct
-{
-  Elf32_Word   p_type;
-  Elf32_Off    p_offset;
-  Elf32_Addr   p_vaddr;
-  Elf32_Addr   p_paddr;
-  Elf32_Word   p_filesz;
-  Elf32_Word   p_memsz;
-  Elf32_Word   p_flags;
-  Elf32_Word   p_align;
-} Elf32_Phdr;
-
-/* Figure 5-9: Dynamic Structure */
-
-typedef struct
-{
-  Elf32_Sword  d_tag;
-  union
-  {
-    Elf32_Word d_val;
-    Elf32_Addr d_ptr;
-  } d_un;
-} Elf32_Dyn;
-
-//extern Elf32_Dyn _DYNAMIC[] ;
-
-#endif /* __INCLUDE_ELF32_H */
+#endif /* __INCLUDE_ELF_H */
diff --git a/include/elf32.h b/include/elf32.h
index e16ae00..dad6450 100644
--- a/include/elf32.h
+++ b/include/elf32.h
@@ -46,205 +46,23 @@
 #include <nuttx/config.h>
 
 #include <stdint.h>
+#include <elf.h>
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Values for Elf32_Ehdr::e_type */
-
-#define ET_NONE           0       /* No file type */
-#define ET_REL            1       /* Relocatable file */
-#define ET_EXEC           2       /* Executable file */
-#define ET_DYN            3       /* Shared object file */
-#define ET_CORE           4       /* Core file */
-#define ET_LOPROC         0xff00  /* Processor-specific */
-#define ET_HIPROC         0xffff  /* Processor-specific */
-
-/* Values for Elf32_Ehdr::e_machine (most of this were not included in the
- * original SCO document but have been gleaned from elsewhere).
- */
-
-#define EM_NONE            0      /* No machine */
-#define EM_M32             1      /* AT&T WE 32100 */
-#define EM_SPARC           2      /* SPARC */
-#define EM_386             3      /* Intel 80386 */
-#define EM_68K             4      /* Motorola 68000 */
-#define EM_88K             5      /* Motorola 88000 */
-#define EM_486             6      /* Intel 486+ */
-#define EM_860             7      /* Intel 80860 */
-#define EM_MIPS            8      /* MIPS R3000 Big-Endian */
-#define EM_MIPS_RS4_BE     10     /* MIPS R4000 Big-Endian */
-#define EM_PARISC          15     /* HPPA */
-#define EM_SPARC32PLUS     18     /* Sun's "v8plus" */
-#define EM_PPC             20     /* PowerPC */
-#define EM_PPC64           21     /* PowerPC64 */
-#define EM_ARM             40     /* ARM */
-#define EM_SH              42     /* SuperH */
-#define EM_SPARCV9         43     /* SPARC v9 64-bit */
-#define EM_IA_64           50     /* HP/Intel IA-64 */
-#define EM_X86_64          62     /* AMD x86-64 */
-#define EM_S390            22     /* IBM S/390 */
-#define EM_CRIS            76     /* Axis Communications 32-bit embedded processor */
-#define EM_V850            87     /* NEC v850 */
-#define EM_M32R            88     /* Renesas M32R */
-#define EM_H8_300          46
-#define EM_ALPHA           0x9026
-#define EM_CYGNUS_V850     0x9080
-#define EM_CYGNUS_M32R     0x9041
-#define EM_S390_OLD        0xa390
-#define EM_FRV             0x5441
-
-/* Values for Elf32_Ehdr::e_version */
-
-#define EV_NONE            0      /* Invalid version */
-#define EV_CURRENT         1      /* The current version */
-
-/* Ehe ELF identifier */
-
-#define EI_MAG0            0      /* File identification */
-#define EI_MAG1            1      /* "  " "            " */
-#define EI_MAG2            2      /* "  " "            " */
-#define EI_MAG3            3      /* "  " "            " */
-#define EI_CLASS           4      /* File class */
-#define EI_DATA            5      /* Data encoding */
-#define EI_VERSION         6      /* File version */
-#define EI_PAD             7      /* Start of padding bytes */
-#define EI_NIDENT          16     /* Size of eident[] */
-
-#define EI_MAGIC_SIZE      4
-#define EI_MAGIC           {0x7f, 'E', 'L', 'F'}
-
-/* Values for EI_CLASS */
-
-#define ELFCLASSNONE       0      /* Invalid class */
-#define ELFCLASS32         1      /* 32-bit objects */
-#define ELFCLASS64         2      /* 64-bit objects */
-
-/* Values for EI_DATA */
-
-#define ELFDATANONE        0     /* Invalid data encoding */
-#define ELFDATA2LSB        1     /* Least significant byte occupying the lowest address */
-#define ELFDATA2MSB        2     /* Most significant byte occupying the lowest address */
-
-/* Figure 4-7: Special Section Indexes */
-
-#define SHN_UNDEF          0
-#define SHN_LORESERVE      0xff00
-#define SHN_LOPROC         0xff00
-#define SHN_HIPROC         0xff1f
-#define SHN_ABS            0xfff1
-#define SHN_COMMON         0xfff2
-#define SHN_HIRESERVE      0xffff
-
-/* Figure 4-9: Section Types, sh_type */
-
-#define SHT_NULL           0
-#define SHT_PROGBITS       1
-#define SHT_SYMTAB         2
-#define SHT_STRTAB         3
-#define SHT_RELA           4
-#define SHT_HASH           5
-#define SHT_DYNAMIC        6
-#define SHT_NOTE           7
-#define SHT_NOBITS         8
-#define SHT_REL            9
-#define SHT_SHLIB          10
-#define SHT_DYNSYM         11
-#define SHT_LOPROC         0x70000000
-#define SHT_HIPROC         0x7fffffff
-#define SHT_LOUSER         0x80000000
-#define SHT_HIUSER         0xffffffff
-
-/* Figure 4-11: Section Attribute Flags, sh_flags */
-
-#define SHF_WRITE          1
-#define SHF_ALLOC          2
-#define SHF_EXECINSTR      4
-#define SHF_MASKPROC       0xf0000000
-
-/* Definitions for Elf32_Sym::st_info */
-
 #define ELF32_ST_BIND(i)   ((i) >> 4)
 #define ELF32_ST_TYPE(i)   ((i) & 0xf)
 #define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf))
 
-/* Figure 4-16: Symbol Binding, ELF32_ST_BIND */
-
-#define STB_LOCAL          0
-#define STB_GLOBAL         1
-#define STB_WEAK           2
-#define STB_LOPROC         13
-#define STB_HIPROC         15
-
-/* Figure 4-17: Symbol Types, ELF32_ST_TYPE */
-
-#define STT_NOTYPE         0
-#define STT_OBJECT         1
-#define STT_FUNC           2
-#define STT_SECTION        3
-#define STT_FILE           4
-#define STT_LOPROC         13
-#define STT_HIPROC         15
-
 /* Definitions for Elf32_Rel*::r_info */
 
 #define ELF32_R_SYM(i)    ((i) >> 8)
 #define ELF32_R_TYPE(i)   ((i) & 0xff)
 #define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff))
 
-/* Figure 5-2: Segment Types, p_type */
-
-#define PT_NULL            0
-#define PT_LOAD            1
-#define PT_DYNAMIC         2
-#define PT_INTERP          3
-#define PT_NOTE            4
-#define PT_SHLIB           5
-#define PT_PHDR            6
-#define PT_LOPROC          0x70000000
-#define PT_HIPROC          0x7fffffff
-
-/* Figure 5-3: Segment Flag Bits, p_flags */
-
-#define PF_X               1          /* Execute */
-#define PF_W               2          /* Write */
-#define PF_R               4          /* Read */
-#define PF_MASKPROC        0xf0000000 /* Unspecified */
-
-/* Figure 5-10: Dynamic Array Tags, d_tag */
-
-#define DT_NULL            0          /* d_un=ignored */
-#define DT_NEEDED          1          /* d_un=d_val */
-#define DT_PLTRELSZ        2          /* d_un=d_val */
-#define DT_PLTGOT          3          /* d_un=d_ptr */
-#define DT_HASH            4          /* d_un=d_ptr */
-#define DT_STRTAB          5          /* d_un=d_ptr */
-#define DT_SYMTAB          6          /* d_un=d_ptr */
-#define DT_RELA            7          /* d_un=d_ptr */
-#define DT_RELASZ          8          /* d_un=d_val */
-#define DT_RELAENT         9          /* d_un=d_val */
-#define DT_STRSZ           10         /* d_un=d_val */
-#define DT_SYMENT          11         /* d_un=d_val */
-#define DT_INIT            12         /* d_un=d_ptr */
-#define DT_FINI            13         /* d_un=d_ptr */
-#define DT_SONAME          14         /* d_un=d_val */
-#define DT_RPATH           15         /* d_un=d_val */
-#define DT_SYMBOLIC        16         /* d_un=ignored */
-#define DT_REL             17         /* d_un=d_ptr */
-#define DT_RELSZ           18         /* d_un=d_val */
-#define DT_RELENT          19         /* d_un=d_val */
-#define DT_PLTREL          20         /* d_un=d_val */
-#define DT_DEBUG           21         /* d_un=d_ptr */
-#define DT_TEXTREL         22         /* d_un=ignored */
-#define DT_JMPREL          23         /* d_un=d_ptr */
-#define DT_BINDNOW         24         /* d_un=ignored */
-#define DT_LOPROC          0x70000000 /* d_un=unspecified */
-#define DT_HIPROC          0x7fffffff /* d_un= unspecified */
+#define ELF_R_SYM(i)      ELF32_R_SYM(i)
 
 /****************************************************************************
  * Public Type Definitions
@@ -347,6 +165,11 @@ typedef struct
   } d_un;
 } Elf32_Dyn;
 
-//extern Elf32_Dyn _DYNAMIC[] ;
+typedef Elf32_Ehdr  Elf_Ehdr;
+typedef Elf32_Rel   Elf_Rel;
+typedef Elf32_Rela  Elf_Rela;
+typedef Elf32_Sym   Elf_Sym;
+typedef Elf32_Shdr  Elf_Shdr;
+typedef Elf32_Word  Elf_Word;
 
 #endif /* __INCLUDE_ELF32_H */
diff --git a/include/elf64.h b/include/elf64.h
new file mode 100644
index 0000000..dc86a61
--- /dev/null
+++ b/include/elf64.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+ * include/elf64.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_ELF64_H
+#define __INCLUDE_ELF64_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <elf.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* See ELF-64 Object File Format: Version 1.5 Draft 2 */
+
+/* Definitions for Elf64_Rel*::r_info */
+
+#define ELF64_R_SYM(i)    ((i) >> 32)
+#define ELF64_R_TYPE(i)   ((i) & 0xffffffffL)
+#define ELF64_R_INFO(s,t) (((s)<< 32) + ((t) & 0xffffffffL))
+
+#define ELF_R_SYM(i)      ELF64_R_SYM(i)
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Table 1: ELF-64 Data Types */
+
+typedef uint64_t  Elf64_Addr;    /* Unsigned program address */
+typedef uint64_t  Elf64_Off;     /* Unsigned file offset */
+typedef uint16_t  Elf64_Half;    /* Unsigned medium integer */
+typedef uint32_t  Elf64_Word;    /* Unsigned long integer */
+typedef int32_t   Elf64_Sword;   /* Signed integer */
+typedef uint64_t  Elf64_Xword;   /* Unsigned long integer */
+typedef int64_t   Elf64_Sxword;  /* Signed large integer */
+
+/* Figure 2: ELF-64 Header */
+
+typedef struct
+{
+  unsigned char e_ident[EI_NIDENT]; /* ELF identification */
+  Elf64_Half    e_type;             /* Object file type */
+  Elf64_Half    e_machine;          /* Machine type */
+  Elf64_Word    e_version;          /* Object file version */
+  Elf64_Addr    e_entry;            /* Entry point address */
+  Elf64_Off     e_phoff;            /* Program header offset */
+  Elf64_Off     e_shoff;            /* Section header offset */
+  Elf64_Word    e_flags;            /* Processor-specific flags */
+  Elf64_Half    e_ehsize;           /* ELF header size */
+  Elf64_Half    e_phentsize;        /* Size of program header entry */
+  Elf64_Half    e_phnum;            /* Number of program header entry */
+  Elf64_Half    e_shentsize;        /* Size of section header entry */
+  Elf64_Half    e_shnum;            /* Number of section header entries */
+  Elf64_Half    e_shstrndx;         /* Section name string table index */
+} Elf64_Ehdr;
+
+/* Figure 3: ELF-64 Section Header */
+
+typedef struct
+{
+  Elf64_Word    sh_name;       /* Section name */
+  Elf64_Word    sh_type;       /* Section type */
+  Elf64_Xword   sh_flags;      /* Section attributes */
+  Elf64_Addr    sh_addr;       /* Virtual address in memory */
+  Elf64_Off     sh_offset;     /* Offset in file */
+  Elf64_Xword   sh_size;       /* Size of section */
+  Elf64_Word    sh_link;       /* Link to other section */
+  Elf64_Word    sh_info;       /* Miscellaneous information */
+  Elf64_Xword   sh_addralign;  /* Address alignment boundary */
+  Elf64_Xword   sh_entsize;    /* Size of entries, if section has table */
+} Elf64_Shdr;
+
+/* Figure 4: ELF-64 Symbol Table Entry */
+
+typedef struct
+{
+  Elf64_Word    st_name;   /* Symbol name */
+  unsigned char st_info;   /* Type and Binding attributes */
+  unsigned char st_other;  /* Reserved */
+  Elf64_Half    st_shndx;  /* Section table index */
+  Elf64_Addr    st_value;  /* Symbol value */
+  Elf64_Xword   st_size;   /* Size of object (e.g., common) */
+} Elf64_Sym;
+
+/* Figure 5: ELF-64 Relocation Entries */
+
+typedef struct
+{
+  Elf64_Addr    r_offset; /* Address of reference */
+  Elf64_Xword   r_info;   /* Symbol index and type of relocation */
+} Elf64_Rel;
+
+typedef struct
+{
+  Elf64_Addr    r_offset; /* Address of reference */
+  Elf64_Xword   r_info;   /* Symbol index and type of relocation */
+  Elf64_Sxword  r_addend; /* Constant part of expression */
+} Elf64_Rela;
+
+/* Figure 6: ELF-64 Program Header Table Entry */
+
+typedef struct
+{
+  Elf64_Word   p_type;     /* Type of segment */
+  Elf64_Word   p_flags;    /* Segment attributes */
+  Elf64_Off    p_offset;   /* Offset in file */
+  Elf64_Addr   p_vaddr;    /* Virtual address in memory */
+  Elf64_Addr   p_paddr;    /* Reserved */
+  Elf64_Word   p_filesz;   /* Size of segment in file */
+  Elf64_Word   p_memsz;    /* Size of segment in memory */
+  Elf64_Word   p_align;    /* Alignment of segment */
+} Elf64_Phdr;
+
+/* Figure 8: Dynamic Table Structure */
+
+typedef struct
+{
+  Elf64_Sxword  d_tag;
+  union
+  {
+    Elf64_Xword d_val;
+    Elf64_Addr  d_ptr;
+  } d_un;
+} Elf64_Dyn;
+
+typedef Elf64_Ehdr  Elf_Ehdr;
+typedef Elf64_Rel   Elf_Rel;
+typedef Elf64_Rela  Elf_Rela;
+typedef Elf64_Sym   Elf_Sym;
+typedef Elf64_Shdr  Elf_Shdr;
+typedef Elf64_Word  Elf_Word;
+
+#endif /* __INCLUDE_ELF64_H */
diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h
index ea3cb08..355a739 100644
--- a/include/nuttx/binfmt/elf.h
+++ b/include/nuttx/binfmt/elf.h
@@ -46,7 +46,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
-#include <elf32.h>
+#include <elf.h>
 
 #include <nuttx/arch.h>
 #include <nuttx/binfmt/binfmt.h>
@@ -110,8 +110,9 @@ struct elf_loadinfo_s
   size_t            textsize;    /* Size of the ELF .text memory allocation */
   size_t            datasize;    /* Size of the ELF .bss/.data memory allocation */
   off_t             filelen;     /* Length of the entire ELF file */
-  Elf32_Ehdr        ehdr;        /* Buffered ELF file header */
-  FAR Elf32_Shdr    *shdr;       /* Buffered ELF section headers */
+
+  Elf_Ehdr          ehdr;        /* Buffered ELF file header */
+  FAR Elf_Shdr      *shdr;       /* Buffered ELF section headers */
   uint8_t           *iobuffer;   /* File I/O buffer */
 
   /* Constructors and destructors */
diff --git a/include/nuttx/elf.h b/include/nuttx/elf.h
index ae90c74..0760f5b 100644
--- a/include/nuttx/elf.h
+++ b/include/nuttx/elf.h
@@ -40,7 +40,7 @@
  * Included Files
  ****************************************************************************/
 
-#include <elf32.h>
+#include <elf.h>
 
 /****************************************************************************
  * Public Function Prototypes
@@ -68,7 +68,7 @@ extern "C"
  ****************************************************************************/
 
 #ifdef CONFIG_LIBC_ARCH_ELF
-bool up_checkarch(FAR const Elf32_Ehdr *hdr);
+bool up_checkarch(FAR const Elf_Ehdr *hdr);
 #endif
 
 /****************************************************************************
@@ -94,10 +94,10 @@ bool up_checkarch(FAR const Elf32_Ehdr *hdr);
  ****************************************************************************/
 
 #ifdef CONFIG_LIBC_ARCH_ELF
-int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
+int up_relocate(FAR const Elf_Rel *rel, FAR const Elf_Sym *sym,
                 uintptr_t addr);
-int up_relocateadd(FAR const Elf32_Rela *rel,
-                   FAR const Elf32_Sym *sym, uintptr_t addr);
+int up_relocateadd(FAR const Elf_Rela *rel,
+                   FAR const Elf_Sym *sym, uintptr_t addr);
 #endif
 
 /****************************************************************************
@@ -117,7 +117,7 @@ int up_relocateadd(FAR const Elf32_Rela *rel,
  ****************************************************************************/
 
 #ifdef CONFIG_CXX_EXCEPTION
-int up_init_exidx(Elf32_Addr address, Elf32_Word size);
+int up_init_exidx(Elf_Addr address, Elf_Word size);
 #endif
 
 #if defined(__cplusplus)
diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h
index e011d8e..44357e9 100644
--- a/include/nuttx/lib/modlib.h
+++ b/include/nuttx/lib/modlib.h
@@ -43,7 +43,7 @@
 #include <nuttx/config.h>
 
 #include <sys/types.h>
-#include <elf32.h>
+#include <elf.h>
 
 #include <nuttx/arch.h>
 #include <nuttx/symtab.h>
@@ -206,8 +206,8 @@ struct mod_loadinfo_s
   size_t            textsize;    /* Size of the module .text memory allocation */
   size_t            datasize;    /* Size of the module .bss/.data memory allocation */
   off_t             filelen;     /* Length of the entire module file */
-  Elf32_Ehdr        ehdr;        /* Buffered module file header */
-  FAR Elf32_Shdr   *shdr;        /* Buffered module section headers */
+  Elf_Ehdr          ehdr;        /* Buffered module file header */
+  FAR Elf_Shdr     *shdr;        /* Buffered module section headers */
   uint8_t          *iobuffer;    /* File I/O buffer */
 
   uint16_t          symtabidx;   /* Symbol table section index */
diff --git a/libs/libc/dlfcn/lib_dlopen.c b/libs/libc/dlfcn/lib_dlopen.c
index dc98d17..d0e504f 100644
--- a/libs/libc/dlfcn/lib_dlopen.c
+++ b/libs/libc/dlfcn/lib_dlopen.c
@@ -98,7 +98,7 @@ static void dldump_loadinfo(FAR struct mod_loadinfo_s *loadinfo)
     {
       for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
         {
-          FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+          FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
           binfo("Sections %d:\n", i);
           binfo("  sh_name:      %08x\n", shdr->sh_name);
           binfo("  sh_type:      %08x\n", shdr->sh_type);
diff --git a/libs/libc/machine/Kconfig b/libs/libc/machine/Kconfig
index 6584ff4..aea5619 100644
--- a/libs/libc/machine/Kconfig
+++ b/libs/libc/machine/Kconfig
@@ -153,6 +153,9 @@ config LIBM_ARCH_TRUNCF
 if ARCH_ARM
 source libs/libc/machine/arm/Kconfig
 endif
+if ARCH_RISCV
+source libs/libc/machine/risc-v/Kconfig
+endif
 if ARCH_SIM
 source libs/libc/machine/sim/Kconfig
 endif
diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs
index c362391..efe95aa 100644
--- a/libs/libc/machine/Make.defs
+++ b/libs/libc/machine/Make.defs
@@ -36,6 +36,9 @@
 ifeq ($(CONFIG_ARCH_ARM),y)
 include ${TOPDIR}/libs/libc/machine/arm/Make.defs
 endif
+ifeq ($(CONFIG_ARCH_RISCV),y)
+include ${TOPDIR}/libs/libc/machine/risc-v/Make.defs
+endif
 ifeq ($(CONFIG_ARCH_SIM),y)
 include ${TOPDIR}/libs/libc/machine/sim/Make.defs
 endif
diff --git a/libs/libc/machine/risc-v/Kconfig b/libs/libc/machine/risc-v/Kconfig
new file mode 100644
index 0000000..9478d84
--- /dev/null
+++ b/libs/libc/machine/risc-v/Kconfig
@@ -0,0 +1,9 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+if ARCH_RV64GC
+source libs/libc/machine/risc-v/rv64/Kconfig
+endif
+
diff --git a/libs/libc/machine/risc-v/Make.defs b/libs/libc/machine/risc-v/Make.defs
new file mode 100644
index 0000000..b312789
--- /dev/null
+++ b/libs/libc/machine/risc-v/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# libs/libc/machine/arm/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifeq ($(CONFIG_ARCH_RV64GC),y)
+include ${TOPDIR}/libs/libc/machine/risc-v/rv64/Make.defs
+endif
diff --git a/libs/libc/machine/risc-v/rv64/Kconfig b/libs/libc/machine/risc-v/rv64/Kconfig
new file mode 100644
index 0000000..f72f3c0
--- /dev/null
+++ b/libs/libc/machine/risc-v/rv64/Kconfig
@@ -0,0 +1,4 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
diff --git a/libs/libc/machine/risc-v/rv64/Make.defs b/libs/libc/machine/risc-v/rv64/Make.defs
new file mode 100644
index 0000000..a08bd9f
--- /dev/null
+++ b/libs/libc/machine/risc-v/rv64/Make.defs
@@ -0,0 +1,28 @@
+############################################################################
+# libs/libc/machine/risc-v/rv64/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifeq ($(CONFIG_LIBC_ARCH_ELF),y)
+
+CSRCS += arch_elf.c
+
+DEPPATH += --dep-path machine/risc-v/rv64
+VPATH += :machine/risc-v/rv64
+
+endif
diff --git a/libs/libc/machine/risc-v/rv64/arch_elf.c b/libs/libc/machine/risc-v/rv64/arch_elf.c
new file mode 100644
index 0000000..259a22f
--- /dev/null
+++ b/libs/libc/machine/risc-v/rv64/arch_elf.c
@@ -0,0 +1,432 @@
+/****************************************************************************
+ * libs/libc/machine/risc-v/rv64/arch_elf.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+#include <assert.h>
+
+#include <arch/elf.h>
+#include <nuttx/elf.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define OPCODE_SW  0x23
+
+/****************************************************************************
+ * Private Data Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_BINFMT_INFO
+struct rname_code_s
+{
+  const char *name;
+  int type;
+};
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_BINFMT_INFO
+static struct rname_code_s _rname_table[] =
+{
+  {"RELAX", R_RISCV_RELAX},
+  {"RISCV_64", R_RISCV_64},
+  {"PCREL_LO12_I", R_RISCV_PCREL_LO12_I},
+  {"PCREL_LO12_S", R_RISCV_PCREL_LO12_S},
+  {"PCREL_HI20", R_RISCV_PCREL_HI20},
+  {"CALL", R_RISCV_CALL},
+  {"BRANCH", R_RISCV_BRANCH},
+  {"RVC_JUMP", R_RISCV_RVC_JUMP},
+  {"RVC_BRANCH", R_RISCV_RVC_BRANCH},
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_BINFMT_INFO
+const char *_get_rname(int type)
+{
+  int i = 0;
+
+  for (i = 0; i < sizeof(_rname_table) / sizeof(struct rname_code_s); i++)
+    {
+      if (_rname_table[i].type == type)
+        {
+          return _rname_table[i].name;
+        }
+    }
+
+  /* Not found in the table */
+
+  return "?????";
+}
+#endif
+
+/****************************************************************************
+ * Name: _get_val, set_val, _add_val
+ *
+ * Description:
+ *   These functions are used when relocating an instruction because we can
+ *   not assume the instruction is word-aligned.
+ *
+ ****************************************************************************/
+
+static uint32_t _get_val(uint16_t *addr)
+{
+  uint32_t ret;
+  ret = *addr | (*(addr + 1)) << 16;
+  return ret;
+}
+
+static void _set_val(uint16_t *addr, uint32_t val)
+{
+  *addr       = (val & 0xffff);
+  *(addr + 1) = (val >> 16);
+
+  /* NOTE: Ensure relocation before execution */
+
+  asm volatile ("fence.i");
+}
+
+static void _add_val(uint16_t *addr, uint32_t val)
+{
+  uint32_t cur = _get_val(addr);
+  _set_val(addr, cur + val);
+}
+
+/****************************************************************************
+ * Name: _calc_imm
+ *
+ * Description:
+ *   Given offset and obtain imm_hi (20bit) and imm_lo (12bit)
+ *
+ * Input Parameters:
+ *   offset - signed 64bit
+ *   imm_hi - signed 20bit
+ *   imm_lo - signed 12bit
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+static void _calc_imm(long offset, long *imm_hi, long *imm_lo)
+{
+  long lo;
+  long hi = offset / 4096;
+  long r  = offset % 4096;
+
+  if (2047 < r)
+    {
+      hi++;
+    }
+  else if (r <= -2048)
+    {
+      hi--;
+    }
+
+  lo = offset - (hi * 4096);
+
+  binfo("offset=%ld: hi=%ld lo=%ld \n",
+        offset, hi, lo);
+
+  ASSERT(-2048 <= lo && lo <= 2047);
+
+  *imm_lo = lo;
+  *imm_hi = hi;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_checkarch
+ *
+ * Description:
+ *   Given the ELF header in 'hdr', verify that the ELF file is appropriate
+ *   for the current, configured architecture.  Every architecture that uses
+ *   the ELF loader must provide this function.
+ *
+ * Input Parameters:
+ *   hdr - The ELF header read from the ELF file.
+ *
+ * Returned Value:
+ *   True if the architecture supports this ELF file.
+ *
+ ****************************************************************************/
+
+bool up_checkarch(FAR const Elf64_Ehdr *ehdr)
+{
+  /* Make sure it's an RISCV executable */
+
+  if (ehdr->e_machine != EM_RISCV)
+    {
+      berr("ERROR: Not for RISCV: e_machine=%04x\n", ehdr->e_machine);
+      return false;
+    }
+
+  /* Make sure that 64-bit objects are supported */
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
+    {
+      berr("ERROR: Need 64-bit objects: e_ident[EI_CLASS]=%02x\n",
+           ehdr->e_ident[EI_CLASS]);
+      return false;
+    }
+
+  /* Verify endian-ness */
+
+#ifdef CONFIG_ENDIAN_BIG
+  if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
+#else
+  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
+#endif
+    {
+      berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n",
+           ehdr->e_ident[EI_DATA]);
+      return false;
+    }
+
+  /* Make sure the entry point address is properly aligned */
+
+  if ((ehdr->e_entry & 1) != 0)
+    {
+      berr("ERROR: Entry point is not properly aligned: %08x\n",
+           ehdr->e_entry);
+    }
+
+  /* TODO:  Check ABI here. */
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: up_relocate and up_relocateadd
+ *
+ * Description:
+ *   Perform on architecture-specific ELF relocation.  Every architecture
+ *   that uses the ELF loader must provide this function.
+ *
+ * Input Parameters:
+ *   rel - The relocation type
+ *   sym - The ELF symbol structure containing the fully resolved value.
+ *         There are a few relocation types for a few architectures that do
+ *         not require symbol information.  For those, this value will be
+ *         NULL.  Implementations of these functions must be able to handle
+ *         that case.
+ *   addr - The address that requires the relocation.
+ *
+ * Returned Value:
+ *   Zero (OK) if the relocation was successful.  Otherwise, a negated errno
+ *   value indicating the cause of the relocation failure.
+ *
+ ****************************************************************************/
+
+int up_relocate(FAR const Elf64_Rel *rel, FAR const Elf64_Sym *sym,
+                uintptr_t addr)
+{
+  berr("Not implemented\n");
+  return -ENOSYS;
+}
+
+int up_relocateadd(FAR const Elf64_Rela *rel, FAR const Elf64_Sym *sym,
+                   uintptr_t addr)
+{
+  long offset;
+  unsigned int relotype;
+
+  /* All relocations depend upon having valid symbol information */
+
+  relotype = ELF64_R_TYPE(rel->r_info);
+
+  if (relotype == R_RISCV_RELAX)
+    {
+      /* NOTE: RELAX has no symbol, so just return */
+
+      binfo("%s at %08lx [%08x] \n",
+            _get_rname(relotype),
+            (long)addr, _get_val((uint16_t *)addr));
+
+      return OK;
+    }
+
+  if (sym == NULL && relotype != R_RISCV_NONE)
+    {
+      return -EINVAL;
+    }
+
+  /* Do relocation based on relocation type */
+
+  switch (relotype)
+    {
+      case R_RISCV_64:
+        {
+          binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n",
+                _get_rname(relotype),
+                (long)addr, _get_val((uint16_t *)addr),
+                sym, (long)sym->st_value);
+
+          _set_val((uint16_t *)addr,
+                   (uint32_t)(sym->st_value + rel->r_addend));
+        }
+        break;
+
+      case R_RISCV_PCREL_LO12_I:
+      case R_RISCV_PCREL_LO12_S:
+        {
+          binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n",
+                _get_rname(relotype),
+                (long)addr, _get_val((uint16_t *)addr),
+                sym, (long)sym->st_value);
+
+          /* NOTE: imm value for mv has been adjusted in previous HI20 */
+        }
+        break;
+
+      case R_RISCV_PCREL_HI20:
+      case R_RISCV_CALL:
+        {
+          binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n",
+                _get_rname(relotype),
+                (long)addr, _get_val((uint16_t *)addr),
+                sym, (long)sym->st_value);
+
+          offset = (long)sym->st_value - (long)addr;
+
+          long imm_hi;
+          long imm_lo;
+
+          _calc_imm(offset, &imm_hi, &imm_lo);
+
+          /* Adjust auipc (add upper immediate to pc) : 20bit */
+
+          _add_val((uint16_t *)addr, (imm_hi << 12));
+
+          if ((_get_val((uint16_t *)(addr + 4)) & 0x7f) == OPCODE_SW)
+            {
+              /* Adjust imm for SW : S-type */
+
+              uint32_t val =
+                (((int32_t)imm_lo >> 5) << 25) +
+                (((int32_t)imm_lo & 0x1f) << 7);
+
+              binfo("imm_lo=%d (%x), val=%x \n", imm_lo, imm_lo, val);
+
+              _add_val((uint16_t *)(addr + 4), val);
+            }
+          else
+            {
+              /* Adjust imm for MV(ADDI)/JALR : I-type */
+
+              _add_val((uint16_t *)(addr + 4), ((int32_t)imm_lo << 20));
+            }
+        }
+        break;
+
+      case R_RISCV_BRANCH:
+        {
+          binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n",
+                _get_rname(relotype),
+                (long)addr, _get_val((uint16_t *)addr),
+                sym, (long)sym->st_value);
+
+          /* P.23 Conditinal Branches : B type (imm=12bit) */
+
+          offset = (long)sym->st_value - (long)addr;
+          uint32_t val = _get_val((uint16_t *)addr) & 0xfe000f80;
+
+          /* NOTE: we assume that a compiler adds an immediate value */
+
+          ASSERT(offset && val);
+
+          binfo("offset for Bx=%ld (0x%x) (val=0x%08x) already set! \n",
+                offset, offset, val);
+        }
+        break;
+
+      case R_RISCV_RVC_JUMP:
+        {
+          binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n",
+                _get_rname(relotype),
+                (long)addr, _get_val((uint16_t *)addr),
+                sym, (long)sym->st_value);
+
+          /* P.111 Table 16.6 : Instruction listings for RVC */
+
+          offset = ((long)sym->st_value - (long)addr);
+          ASSERT(-2048 <= offset && offset <= 2047);
+
+          uint16_t val = (*(uint16_t *)addr) & 0x1ffc;
+
+          /* NOTE: we assume that a compiler adds an immediate value */
+
+          ASSERT(offset && val);
+
+          binfo("offset for C.J=%ld (0x%x) (val=0x%04x) already set! \n",
+                offset, offset, val);
+        }
+        break;
+
+      case R_RISCV_RVC_BRANCH:
+        {
+          binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n",
+                _get_rname(relotype),
+                (long)addr, _get_val((uint16_t *)addr),
+                sym, (long)sym->st_value);
+
+          /* P.111 Table 16.6 : Instruction listings for RVC */
+
+          offset = ((long)sym->st_value - (long)addr);
+          ASSERT(-256 <= offset && offset <= 255);
+
+          uint16_t val = (*(uint16_t *)addr) & 0x1c7c;
+
+          /* NOTE: we assume that a compiler adds an immediate value */
+
+          ASSERT(offset && val);
+
+          binfo("offset for C.Bx=%ld (0x%x) (val=0x%04x) already set!\n",
+                offset, offset, val);
+        }
+        break;
+
+      default:
+        berr("ERROR: Unsupported relocation: %d\n",
+             ELF64_R_TYPE(rel->r_info));
+        ASSERT(false);
+        return -EINVAL;
+    }
+
+  return OK;
+}
diff --git a/libs/libc/modlib/modlib.h b/libs/libc/modlib/modlib.h
index 1c4fb9a..26b1112 100644
--- a/libs/libc/modlib/modlib.h
+++ b/libs/libc/modlib/modlib.h
@@ -64,7 +64,7 @@
  *
  ****************************************************************************/
 
-int modlib_verifyheader(FAR const Elf32_Ehdr *header);
+int modlib_verifyheader(FAR const Elf_Ehdr *header);
 
 /****************************************************************************
  * Name: modlib_findsymtab
@@ -98,7 +98,7 @@ int modlib_findsymtab(FAR struct mod_loadinfo_s *loadinfo);
  ****************************************************************************/
 
 int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index,
-                   FAR Elf32_Sym *sym);
+                   FAR Elf_Sym *sym);
 
 /****************************************************************************
  * Name: modlib_symvalue
@@ -125,7 +125,7 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index,
  ****************************************************************************/
 
 int modlib_symvalue(FAR struct module_s *modp,
-                    FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym);
+                    FAR struct mod_loadinfo_s *loadinfo, FAR Elf_Sym *sym);
 
 /****************************************************************************
  * Name: modlib_loadshdrs
diff --git a/libs/libc/modlib/modlib_bind.c b/libs/libc/modlib/modlib_bind.c
index cb7af8d..866a502 100644
--- a/libs/libc/modlib/modlib_bind.c
+++ b/libs/libc/modlib/modlib_bind.c
@@ -56,15 +56,15 @@
  ****************************************************************************/
 
 /* REVISIT:  This naming breaks the NuttX coding standard, but is consistent
- * with legacy naming of other ELF32 types.
+ * with legacy naming of other ELF types.
  */
 
 typedef struct
 {
   dq_entry_t      entry;
-  Elf32_Sym       sym;
+  Elf_Sym         sym;
   int             idx;
-} Elf32_SymCache;
+} Elf_SymCache;
 
 /****************************************************************************
  * Private Functions
@@ -74,13 +74,13 @@ typedef struct
  * Name: modlib_readrels
  *
  * Description:
- *   Read the (ELF32_Rel structure * buffer count) into memory.
+ *   Read the (ELF_Rel structure * buffer count) into memory.
  *
  ****************************************************************************/
 
 static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo,
-                                  FAR const Elf32_Shdr *relsec,
-                                  int index, FAR Elf32_Rel *rels,
+                                  FAR const Elf_Shdr *relsec,
+                                  int index, FAR Elf_Rel *rels,
                                   int count)
 {
   off_t offset;
@@ -88,7 +88,7 @@ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo,
 
   /* Verify that the symbol table index lies within symbol table */
 
-  if (index < 0 || index > (relsec->sh_size / sizeof(Elf32_Rel)))
+  if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rel)))
     {
       berr("ERROR: Bad relocation symbol index: %d\n", index);
       return -EINVAL;
@@ -96,8 +96,8 @@ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo,
 
   /* Get the file offset to the symbol table entry */
 
-  offset = sizeof(Elf32_Rel) * index;
-  size   = sizeof(Elf32_Rel) * count;
+  offset = sizeof(Elf_Rel) * index;
+  size   = sizeof(Elf_Rel) * count;
   if (offset + size > relsec->sh_size)
     {
       size = relsec->sh_size - offset;
@@ -110,6 +110,45 @@ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo,
 }
 
 /****************************************************************************
+ * Name: modlib_readrelas
+ *
+ * Description:
+ *   Read the (ELF_Rela structure * buffer count) into memory.
+ *
+ ****************************************************************************/
+
+static inline int modlib_readrelas(FAR struct mod_loadinfo_s *loadinfo,
+                                   FAR const Elf_Shdr *relsec,
+                                   int index, FAR Elf_Rela *relas,
+                                   int count)
+{
+  off_t offset;
+  int size;
+
+  /* Verify that the symbol table index lies within symbol table */
+
+  if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rela)))
+    {
+      berr("ERROR: Bad relocation symbol index: %d\n", index);
+      return -EINVAL;
+    }
+
+  /* Get the file offset to the symbol table entry */
+
+  offset = sizeof(Elf_Rela) * index;
+  size   = sizeof(Elf_Rela) * count;
+  if (offset + size > relsec->sh_size)
+    {
+      size = relsec->sh_size - offset;
+    }
+
+  /* And, finally, read the symbol table entry into memory */
+
+  return modlib_read(loadinfo, (FAR uint8_t *)relas, size,
+                     relsec->sh_offset + offset);
+}
+
+/****************************************************************************
  * Name: modlib_relocate and modlib_relocateadd
  *
  * Description:
@@ -125,12 +164,12 @@ static int modlib_relocate(FAR struct module_s *modp,
                            FAR struct mod_loadinfo_s *loadinfo, int relidx)
 
 {
-  FAR Elf32_Shdr *relsec = &loadinfo->shdr[relidx];
-  FAR Elf32_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info];
-  FAR Elf32_Rel  *rels;
-  FAR Elf32_Rel  *rel;
-  FAR Elf32_SymCache *cache;
-  FAR Elf32_Sym  *sym;
+  FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx];
+  FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info];
+  FAR Elf_Rel  *rels;
+  FAR Elf_Rel  *rel;
+  FAR Elf_SymCache *cache;
+  FAR Elf_Sym  *sym;
   FAR dq_entry_t *e;
   dq_queue_t      q;
   uintptr_t       addr;
@@ -139,7 +178,7 @@ static int modlib_relocate(FAR struct module_s *modp,
   int             i;
   int             j;
 
-  rels = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf32_Rel));
+  rels = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rel));
   if (!rels)
     {
       berr("Failed to allocate memory for elf relocation rels\n");
@@ -155,7 +194,7 @@ static int modlib_relocate(FAR struct module_s *modp,
 
   ret = OK;
 
-  for (i = j = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++)
+  for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rel); i++)
     {
       /* Read the relocation entry into memory */
 
@@ -176,14 +215,14 @@ static int modlib_relocate(FAR struct module_s *modp,
        * in a bit-field within the r_info element.
        */
 
-      symidx = ELF32_R_SYM(rel->r_info);
+      symidx = ELF_R_SYM(rel->r_info);
 
       /* First try the cache */
 
       sym = NULL;
       for (e = dq_peek(&q); e; e = dq_next(e))
         {
-          cache = (FAR Elf32_SymCache *)e;
+          cache = (FAR Elf_SymCache *)e;
           if (cache->idx == symidx)
             {
               dq_rem(&cache->entry, &q);
@@ -201,7 +240,7 @@ static int modlib_relocate(FAR struct module_s *modp,
         {
           if (j < CONFIG_MODLIB_SYMBOL_CACHECOUNT)
             {
-              cache = lib_malloc(sizeof(Elf32_SymCache));
+              cache = lib_malloc(sizeof(Elf_SymCache));
               if (!cache)
                 {
                   berr("Failed to allocate memory for elf symbols\n");
@@ -212,7 +251,7 @@ static int modlib_relocate(FAR struct module_s *modp,
             }
           else
             {
-              cache = (FAR Elf32_SymCache *)dq_remlast(&q);
+              cache = (FAR Elf_SymCache *)dq_remlast(&q);
             }
 
           sym = &cache->sym;
@@ -301,8 +340,177 @@ static int modlib_relocate(FAR struct module_s *modp,
 static int modlib_relocateadd(FAR struct module_s *modp,
                            FAR struct mod_loadinfo_s *loadinfo, int relidx)
 {
-  berr("ERROR: Not implemented\n");
-  return -ENOSYS;
+  FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx];
+  FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info];
+  FAR Elf_Rela *relas;
+  FAR Elf_Rela *rela;
+  FAR Elf_SymCache *cache;
+  FAR Elf_Sym  *sym;
+  FAR dq_entry_t *e;
+  dq_queue_t      q;
+  uintptr_t       addr;
+  int             symidx;
+  int             ret;
+  int             i;
+  int             j;
+
+  relas = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rela));
+  if (!relas)
+    {
+      berr("Failed to allocate memory for elf relocation relas\n");
+      return -ENOMEM;
+    }
+
+  dq_init(&q);
+
+  /* Examine each relocation in the section.  'relsec' is the section
+   * containing the relations.  'dstsec' is the section containing the data
+   * to be relocated.
+   */
+
+  ret = OK;
+
+  for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rela); i++)
+    {
+      /* Read the relocation entry into memory */
+
+      rela = &relas[i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT];
+
+      if (!(i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT))
+        {
+          ret = modlib_readrelas(loadinfo, relsec, i, relas, CONFIG_MODLIB_RELOCATION_BUFFERCOUNT);
+          if (ret < 0)
+          {
+              berr("ERROR: Section %d reloc %d: Failed to read relocation entry: %d\n",
+                   relidx, i, ret);
+              break;
+          }
+        }
+
+      /* Get the symbol table index for the relocation.  This is contained
+       * in a bit-field within the r_info element.
+       */
+
+      symidx = ELF_R_SYM(rela->r_info);
+
+      /* First try the cache */
+
+      sym = NULL;
+      for (e = dq_peek(&q); e; e = dq_next(e))
+        {
+          cache = (FAR Elf_SymCache *)e;
+          if (cache->idx == symidx)
+            {
+              dq_rem(&cache->entry, &q);
+              dq_addfirst(&cache->entry, &q);
+              sym = &cache->sym;
+              break;
+            }
+        }
+
+      /* If the symbol was not found in the cache, we will need to read the
+       * symbol from the file.
+       */
+
+      if (sym == NULL)
+        {
+          if (j < CONFIG_MODLIB_SYMBOL_CACHECOUNT)
+            {
+              cache = lib_malloc(sizeof(Elf_SymCache));
+              if (!cache)
+                {
+                  berr("Failed to allocate memory for elf symbols\n");
+                  ret = -ENOMEM;
+                  break;
+                }
+              j++;
+            }
+          else
+            {
+              cache = (FAR Elf_SymCache *)dq_remlast(&q);
+            }
+
+          sym = &cache->sym;
+
+          /* Read the symbol table entry into memory */
+
+          ret = modlib_readsym(loadinfo, symidx, sym);
+          if (ret < 0)
+            {
+              berr("ERROR: Section %d reloc %d: Failed to read symbol[%d]: %d\n",
+                   relidx, i, symidx, ret);
+              lib_free(cache);
+              break;
+            }
+
+          /* Get the value of the symbol (in sym.st_value) */
+
+          ret = modlib_symvalue(modp, loadinfo, sym);
+          if (ret < 0)
+            {
+              /* The special error -ESRCH is returned only in one condition:  The
+               * symbol has no name.
+               *
+               * There are a few relocations for a few architectures that do
+               * no depend upon a named symbol.  We don't know if that is the
+               * case here, but we will use a NULL symbol pointer to indicate
+               * that case to up_relocate().  That function can then do what
+               * is best.
+               */
+
+              if (ret == -ESRCH)
+                {
+                  berr("ERROR: Section %d reloc %d: Undefined symbol[%d] has no name: %d\n",
+                      relidx, i, symidx, ret);
+                }
+              else
+                {
+                  berr("ERROR: Section %d reloc %d: Failed to get value of symbol[%d]: %d\n",
+                      relidx, i, symidx, ret);
+                  lib_free(cache);
+                  break;
+                }
+            }
+
+          cache->idx = symidx;
+          dq_addfirst(&cache->entry, &q);
+        }
+
+      if (sym->st_shndx == SHN_UNDEF && sym->st_name == 0)
+        {
+          sym = NULL;
+        }
+
+      /* Calculate the relocation address. */
+
+      if (rela->r_offset < 0 || rela->r_offset > dstsec->sh_size - sizeof(uint32_t))
+        {
+          berr("ERROR: Section %d reloc %d: Relocation address out of range, offset %d size %d\n",
+               relidx, i, rela->r_offset, dstsec->sh_size);
+          ret = -EINVAL;
+          break;
+        }
+
+      addr = dstsec->sh_addr + rela->r_offset;
+
+      /* Now perform the architecture-specific relocation */
+
+      ret = up_relocateadd(rela, sym, addr);
+      if (ret < 0)
+        {
+          berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", relidx, i, ret);
+          break;
+        }
+    }
+
+  lib_free(relas);
+  while ((e = dq_peek(&q)))
+    {
+      dq_rem(e, &q);
+      lib_free(e);
+    }
+
+  return ret;
 }
 
 /****************************************************************************
diff --git a/libs/libc/modlib/modlib_init.c b/libs/libc/modlib/modlib_init.c
index fdf8771..18d11c7 100644
--- a/libs/libc/modlib/modlib_init.c
+++ b/libs/libc/modlib/modlib_init.c
@@ -170,7 +170,7 @@ int modlib_initialize(FAR const char *filename,
   /* Read the ELF ehdr from offset 0 */
 
   ret = modlib_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr,
-                    sizeof(Elf32_Ehdr), 0);
+                    sizeof(Elf_Ehdr), 0);
   if (ret < 0)
     {
       berr("ERROR: Failed to read ELF header: %d\n", ret);
@@ -178,7 +178,7 @@ int modlib_initialize(FAR const char *filename,
     }
 
   modlib_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr,
-                    sizeof(Elf32_Ehdr));
+                    sizeof(Elf_Ehdr));
 
   /* Verify the ELF header */
 
diff --git a/libs/libc/modlib/modlib_load.c b/libs/libc/modlib/modlib_load.c
index 24c7052..82daa22 100644
--- a/libs/libc/modlib/modlib_load.c
+++ b/libs/libc/modlib/modlib_load.c
@@ -99,7 +99,7 @@ static void modlib_elfsize(struct mod_loadinfo_s *loadinfo)
 
   for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
     {
-      FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+      FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
 
       /* SHF_ALLOC indicates that the section requires memory during
        * execution.
@@ -157,7 +157,7 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
 
   for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
     {
-      FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+      FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
 
       /* SHF_ALLOC indicates that the section requires memory during
        * execution */
diff --git a/libs/libc/modlib/modlib_sections.c b/libs/libc/modlib/modlib_sections.c
index 3b55882..fdb6218 100644
--- a/libs/libc/modlib/modlib_sections.c
+++ b/libs/libc/modlib/modlib_sections.c
@@ -67,9 +67,9 @@
  ****************************************************************************/
 
 static inline int modlib_sectname(FAR struct mod_loadinfo_s *loadinfo,
-                                  FAR const Elf32_Shdr *shdr)
+                                  FAR const Elf_Shdr *shdr)
 {
-  FAR Elf32_Shdr *shstr;
+  FAR Elf_Shdr *shstr;
   FAR uint8_t *buffer;
   off_t  offset;
   size_t readlen;
@@ -203,7 +203,7 @@ int modlib_loadshdrs(FAR struct mod_loadinfo_s *loadinfo)
 
   /* Allocate memory to hold a working copy of the sector header table */
 
-  loadinfo->shdr = (FAR FAR Elf32_Shdr *)lib_malloc(shdrsize);
+  loadinfo->shdr = (FAR FAR Elf_Shdr *)lib_malloc(shdrsize);
   if (!loadinfo->shdr)
     {
       berr("ERROR: Failed to allocate the section header table. Size: %ld\n",
@@ -243,7 +243,7 @@ int modlib_loadshdrs(FAR struct mod_loadinfo_s *loadinfo)
 int modlib_findsection(FAR struct mod_loadinfo_s *loadinfo,
                        FAR const char *sectname)
 {
-  FAR const Elf32_Shdr *shdr;
+  FAR const Elf_Shdr *shdr;
   int ret;
   int i;
 
diff --git a/libs/libc/modlib/modlib_symbols.c b/libs/libc/modlib/modlib_symbols.c
index f14cba0..d320d96 100644
--- a/libs/libc/modlib/modlib_symbols.c
+++ b/libs/libc/modlib/modlib_symbols.c
@@ -89,7 +89,7 @@ struct mod_exportinfo_s
  ****************************************************************************/
 
 static int modlib_symname(FAR struct mod_loadinfo_s *loadinfo,
-                          FAR const Elf32_Sym *sym)
+                          FAR const Elf_Sym *sym)
 {
   FAR uint8_t *buffer;
   off_t  offset;
@@ -276,14 +276,14 @@ int modlib_findsymtab(FAR struct mod_loadinfo_s *loadinfo)
  ****************************************************************************/
 
 int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index,
-                   FAR Elf32_Sym *sym)
+                   FAR Elf_Sym *sym)
 {
-  FAR Elf32_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
+  FAR Elf_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
   off_t offset;
 
   /* Verify that the symbol table index lies within symbol table */
 
-  if (index < 0 || index > (symtab->sh_size / sizeof(Elf32_Sym)))
+  if (index < 0 || index > (symtab->sh_size / sizeof(Elf_Sym)))
     {
       berr("ERROR: Bad relocation symbol index: %d\n", index);
       return -EINVAL;
@@ -291,11 +291,11 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index,
 
   /* Get the file offset to the symbol table entry */
 
-  offset = symtab->sh_offset + sizeof(Elf32_Sym) * index;
+  offset = symtab->sh_offset + sizeof(Elf_Sym) * index;
 
   /* And, finally, read the symbol table entry into memory */
 
-  return modlib_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset);
+  return modlib_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf_Sym), offset);
 }
 
 /****************************************************************************
@@ -323,7 +323,7 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index,
  ****************************************************************************/
 
 int modlib_symvalue(FAR struct module_s *modp,
-                    FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym)
+                    FAR struct mod_loadinfo_s *loadinfo, FAR Elf_Sym *sym)
 {
   FAR const struct symtab_s *symbol;
   struct mod_exportinfo_s exportinfo;
@@ -416,7 +416,7 @@ int modlib_symvalue(FAR struct module_s *modp,
               loadinfo->iobuffer, sym->st_value, symbol->sym_value,
               sym->st_value + symbol->sym_value);
 
-        sym->st_value += (Elf32_Word)((uintptr_t)symbol->sym_value);
+        sym->st_value += (Elf_Word)((uintptr_t)symbol->sym_value);
       }
       break;
 
diff --git a/libs/libc/modlib/modlib_verify.c b/libs/libc/modlib/modlib_verify.c
index 12040db..97bdf3d 100644
--- a/libs/libc/modlib/modlib_verify.c
+++ b/libs/libc/modlib/modlib_verify.c
@@ -77,7 +77,7 @@ static const char g_modmagic[EI_MAGIC_SIZE] =
  *
  ****************************************************************************/
 
-int modlib_verifyheader(FAR const Elf32_Ehdr *ehdr)
+int modlib_verifyheader(FAR const Elf_Ehdr *ehdr)
 {
   if (!ehdr)
     {
diff --git a/libs/libxx/libxx__gnu_unwind_find_exidx.cxx b/libs/libxx/libxx__gnu_unwind_find_exidx.cxx
index 7f2ed19..08b67fa 100644
--- a/libs/libxx/libxx__gnu_unwind_find_exidx.cxx
+++ b/libs/libxx/libxx__gnu_unwind_find_exidx.cxx
@@ -85,7 +85,7 @@
 
 extern "C"
 {
-  int up_init_exidx(Elf32_Addr start, Elf32_Word size)
+  int up_init_exidx(Elf_Addr start, Elf_Word size)
   {
     __exidx_start_elf = (__EIT_entry *) start;
     __exidx_end_elf   = __exidx_start_elf + size;
diff --git a/sched/module/mod_insmod.c b/sched/module/mod_insmod.c
index 0cc2a8c..2209bef 100644
--- a/sched/module/mod_insmod.c
+++ b/sched/module/mod_insmod.c
@@ -106,7 +106,7 @@ static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
     {
       for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
         {
-          FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
+          FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
           binfo("Sections %d:\n", i);
           binfo("  sh_name:      %08x\n", shdr->sh_name);
           binfo("  sh_type:      %08x\n", shdr->sh_type);