diff --git a/arch/x86_64/include/elf.h b/arch/x86_64/include/elf.h
new file mode 100644
index 0000000000..f4c87f1402
--- /dev/null
+++ b/arch/x86_64/include/elf.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+ * arch/x86_64/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_X86_64_INCLUDE_ELF_H
+#define __ARCH_X86_64_INCLUDE_ELF_H
+
+/****************************************************************************
+ * Pre-processor Prototypes
+ ****************************************************************************/
+
+#define R_X86_64_NONE   0
+#define R_X86_64_64     1
+#define R_X86_64_PC32   2
+#define R_X86_64_PLT32  4
+#define R_X86_64_32     10
+#define R_X86_64_32S    11
+#define R_X86_64_PC64   24
+
+/* 4.3.1 ELF Identification.  Should have:
+ *
+ * e_machine         = EM_X86_64
+ */
+
+#define EM_ARCH      EM_X86_64
+
+#define EF_FLAG      0
+
+#endif /* __ARCH_X86_64_INCLUDE_ELF_H */
diff --git a/arch/x86_64/src/common/Toolchain.defs b/arch/x86_64/src/common/Toolchain.defs
index 2f0a4cdd6d..6f6f1ade9e 100644
--- a/arch/x86_64/src/common/Toolchain.defs
+++ b/arch/x86_64/src/common/Toolchain.defs
@@ -129,3 +129,23 @@ AFLAGS += -Wa,--divide
 endif
 
 EXEEXT = .elf
+
+# Loadable module definitions
+
+CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden
+LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)
+
+# ELF module definitions
+
+CELFFLAGS = $(CFLAGS) -fvisibility=hidden
+CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
+
+LDELFFLAGS = -r -e main --gc-sections
+LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld)
+
+# -fno-pic to avoid GOT relocations
+# -mcmodel=large to avoid out-of-range 32-bit relocations
+
+CMODULEFLAGS += -fno-pic -mcmodel=large
+CELFFLAGS += -fno-pic -mcmodel=large
+CXXELFFLAGS += -fno-pic -mcmodel=large
diff --git a/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs b/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs
index e55817d63f..1bcd75dbc6 100644
--- a/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs
+++ b/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs
@@ -22,4 +22,4 @@ include $(TOPDIR)/.config
 include $(TOPDIR)/tools/Config.mk
 include $(TOPDIR)/arch/x86_64/src/intel64/Toolchain.defs
 
-ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)qemu.ld
+ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)qemu.ld
\ No newline at end of file
diff --git a/libs/libc/machine/x86_64/CMakeLists.txt b/libs/libc/machine/x86_64/CMakeLists.txt
index 1fcd9ef065..3c9e94ca89 100644
--- a/libs/libc/machine/x86_64/CMakeLists.txt
+++ b/libs/libc/machine/x86_64/CMakeLists.txt
@@ -22,4 +22,8 @@ add_subdirectory(gnu)
 
 set(SRCS)
 
+if(CONFIG_LIBC_ARCH_ELF)
+  list(APPEND SRCS arch_elf.c)
+endif()
+
 target_sources(c PRIVATE ${SRCS})
diff --git a/libs/libc/machine/x86_64/Make.defs b/libs/libc/machine/x86_64/Make.defs
index a7d570207f..e30495401a 100644
--- a/libs/libc/machine/x86_64/Make.defs
+++ b/libs/libc/machine/x86_64/Make.defs
@@ -18,6 +18,10 @@
 #
 ############################################################################
 
+ifeq ($(CONFIG_LIBC_ARCH_ELF),y)
+CSRCS += arch_elf64.c
+endif
+
 ifeq ($(CONFIG_X86_64_MEMCMP),y)
 ASRCS += arch_memcmp.S
 endif
diff --git a/libs/libc/machine/x86_64/arch_elf64.c b/libs/libc/machine/x86_64/arch_elf64.c
new file mode 100644
index 0000000000..7dad5fb70c
--- /dev/null
+++ b/libs/libc/machine/x86_64/arch_elf64.c
@@ -0,0 +1,183 @@
+/****************************************************************************
+ * libs/libc/machine/x86_64/arch_elf64.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.
+ *
+ ****************************************************************************/
+
+/* References:
+ *    AMD64 ABI Draft 0.98
+ *    http://refspecs.linuxbase.org/elf/x86_64-abi-0.98.pdf
+ *    4.4 Relocation
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+#include <assert.h>
+
+#include <nuttx/elf.h>
+
+/****************************************************************************
+ * 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(const Elf64_Ehdr *ehdr)
+{
+  /* Make sure it's an x86_64 executable */
+
+  if (ehdr->e_machine != EM_X86_64)
+    {
+      berr("ERROR: Not for x86_64: 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
+#error x86_64 is LE
+#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;
+    }
+
+  /* TODO:  Check ABI here. */
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: up_relocate and up_relocateadd
+ *
+ * Description:
+ *   Perform an 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(const Elf64_Rel *rel, const Elf64_Sym *sym, uintptr_t addr,
+                FAR void *arch_data)
+{
+  berr("Not implemented\n");
+  return -ENOSYS;
+}
+
+int up_relocateadd(const Elf64_Rela *rel, const Elf64_Sym *sym,
+                   uintptr_t addr, FAR void *arch_data)
+{
+  unsigned int relotype;
+  uint64_t value;
+
+  relotype = ELF64_R_TYPE(rel->r_info);
+
+  if (sym == NULL && relotype != R_X86_64_NONE)
+    {
+      return -EINVAL;
+    }
+
+  /* A ... The addend (rel->r_addend)
+   * P ... The location (addr)
+   * L ... The PLT location (sym->st_value)
+   * S ... symbol value (sym->st_value)
+   */
+
+  switch (relotype)
+    {
+      case R_X86_64_64: /* S + A */
+        *(uint64_t *)addr = sym->st_value + rel->r_addend;
+        break;
+      case R_X86_64_PC32:  /* S + A - P */
+      case R_X86_64_PLT32: /* L + A - P */
+        value = sym->st_value + rel->r_addend - addr;
+        if ((int32_t)value != value)
+          {
+            berr("ERROR: Out of range relocation: %d\n", relotype);
+            return -EINVAL;
+          }
+
+        *(uint32_t *)addr = value;
+        break;
+      case R_X86_64_PC64:  /* S + A - P */
+        value = sym->st_value + rel->r_addend - addr;
+        *(uint64_t *)addr = value;
+        break;
+      case R_X86_64_32:  /* S + A */
+      case R_X86_64_32S: /* S + A */
+        value = sym->st_value + rel->r_addend;
+        if ((relotype == R_X86_64_32 && (uint32_t)value != value) ||
+            (relotype == R_X86_64_32S && (int32_t)value != value))
+          {
+            berr("ERROR: Out of range relocation: %d\n", relotype);
+            return -EINVAL;
+          }
+
+        *(uint32_t *)addr = value;
+        break;
+      default:
+        berr("ERROR: Unsupported relocation: %d\n", relotype);
+        return -EINVAL;
+    }
+
+  return OK;
+}