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

xiaoxiang pushed a commit to branch releases/12.7
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 3b0e2be0589da57d073e6e219beefb14b64061a8
Author: dongjiuzhu1 <[email protected]>
AuthorDate: Wed Nov 29 22:25:47 2023 +0800

    binfmt/modlib: support loading each sections to different memory for 
Relocate object
    
    The feature depends on ARCH_USE_SEPARATED_SECTION
    the different memory area has different access speed and cache
    capability, so the arch can custom allocate them based on
    section names to achieve performance optimization
    
    test:
    sim:elf
    sim:sotest
    
    Signed-off-by: dongjiuzhu1 <[email protected]>
---
 arch/Kconfig                                       |   8 ++
 arch/sim/src/Makefile                              |   2 +-
 arch/sim/src/sim/CMakeLists.txt                    |   2 +-
 .../src/sim/{sim_textheap.c => sim_sectionheap.c}  |  60 ++++++++-
 binfmt/binfmt_unloadmodule.c                       |  33 +++++
 binfmt/elf.c                                       |  16 +++
 binfmt/libelf/libelf_addrenv.c                     |  62 +++++++--
 binfmt/libelf/libelf_bind.c                        |  24 +++-
 binfmt/libelf/libelf_load.c                        | 105 ++++++++++++++-
 include/nuttx/arch.h                               |  14 +-
 include/nuttx/binfmt/binfmt.h                      |   4 +
 include/nuttx/binfmt/elf.h                         |   4 +
 include/nuttx/lib/modlib.h                         |   4 +
 libs/libc/dlfcn/lib_dlopen.c                       |   8 ++
 libs/libc/modlib/modlib_bind.c                     |  24 +++-
 libs/libc/modlib/modlib_load.c                     | 145 +++++++++++++++++----
 libs/libc/modlib/modlib_unload.c                   |  28 ++++
 sched/module/mod_insmod.c                          |   8 ++
 18 files changed, 505 insertions(+), 46 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 2ec252ecae..9893376350 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -670,6 +670,14 @@ config ARCH_USE_DATA_HEAP
                This option enables architecture-specific memory allocator
                for dynamic data loading.
 
+config ARCH_USE_SEPARATED_SECTION
+       bool "Enable separate section allocation for dynamic loading"
+       default n
+       depends on ARCH_USE_TEXT_HEAP || ARCH_USE_DATA_HEAP
+       ---help---
+               This option enables loading different sections into different
+               memory areas, allowing for different speeds.
+
 menuconfig ARCH_ADDRENV
        bool "Address environments"
        default n
diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile
index a2632b38e2..2f25984ed4 100644
--- a/arch/sim/src/Makefile
+++ b/arch/sim/src/Makefile
@@ -81,7 +81,7 @@ CSRCS  = sim_initialize.c sim_idle.c sim_doirq.c 
sim_initialstate.c
 CSRCS += sim_createstack.c sim_usestack.c sim_releasestack.c sim_stackframe.c
 CSRCS += sim_exit.c sim_schedulesigaction.c sim_switchcontext.c sim_heap.c
 CSRCS += sim_uart.c sim_copyfullstate.c sim_sigdeliver.c sim_tcbinfo.c 
sim_cpuinfo.c
-CSRCS += sim_registerdump.c sim_saveusercontext.c sim_textheap.c
+CSRCS += sim_registerdump.c sim_saveusercontext.c sim_sectionheap.c
 CSRCS += sim_checkhostfstypes.c
 
 ifeq ($(CONFIG_SCHED_BACKTRACE),y)
diff --git a/arch/sim/src/sim/CMakeLists.txt b/arch/sim/src/sim/CMakeLists.txt
index ccd91cfc9b..a4e114b147 100644
--- a/arch/sim/src/sim/CMakeLists.txt
+++ b/arch/sim/src/sim/CMakeLists.txt
@@ -57,7 +57,7 @@ list(
   sim_registerdump.c
   sim_saveusercontext.c
   sim_tcbinfo.c
-  sim_textheap.c
+  sim_sectionheap.c
   sim_checkhostfstypes.c)
 
 if(CONFIG_HOST_X86_64)
diff --git a/arch/sim/src/sim/sim_textheap.c 
b/arch/sim/src/sim/sim_sectionheap.c
similarity index 63%
rename from arch/sim/src/sim/sim_textheap.c
rename to arch/sim/src/sim/sim_sectionheap.c
index 6fa233201e..411190b51b 100644
--- a/arch/sim/src/sim/sim_textheap.c
+++ b/arch/sim/src/sim/sim_sectionheap.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/sim/src/sim/sim_textheap.c
+ * arch/sim/src/sim/sim_sectionheap.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -32,6 +32,7 @@
  ****************************************************************************/
 
 static struct mm_heap_s *g_textheap;
+static struct mm_heap_s *g_dataheap;
 
 /****************************************************************************
  * Public Functions
@@ -45,7 +46,11 @@ static struct mm_heap_s *g_textheap;
  *
  ****************************************************************************/
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+void *up_textheap_memalign(const char *sectname, size_t align, size_t size)
+#else
 void *up_textheap_memalign(size_t align, size_t size)
+#endif
 {
   if (g_textheap == NULL)
     {
@@ -85,3 +90,56 @@ bool up_textheap_heapmember(void *p)
 {
   return g_textheap != NULL && mm_heapmember(g_textheap, p);
 }
+
+/****************************************************************************
+ * Name: up_dataheap_memalign
+ *
+ * Description:
+ *   Allocate memory for data sections with the specified alignment.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+void *up_dataheap_memalign(const char *sectname, size_t align, size_t size)
+#else
+void *up_dataheap_memalign(size_t align, size_t size)
+#endif
+{
+  if (g_dataheap == NULL)
+    {
+      g_dataheap = mm_initialize("dataheap",
+                                 host_allocheap(SIM_HEAP_SIZE, true),
+                                 SIM_HEAP_SIZE);
+    }
+
+  return mm_memalign(g_dataheap, align, size);
+}
+
+/****************************************************************************
+ * Name: up_dataheap_free
+ *
+ * Description:
+ *   Free memory allocated for data sections.
+ *
+ ****************************************************************************/
+
+void up_dataheap_free(void *p)
+{
+  if (g_dataheap != NULL)
+    {
+      mm_free(g_dataheap, p);
+    }
+}
+
+/****************************************************************************
+ * Name: up_dataheap_heapmember
+ *
+ * Description:
+ *   Test if memory is from data heap.
+ *
+ ****************************************************************************/
+
+bool up_dataheap_heapmember(void *p)
+{
+  return g_dataheap != NULL && mm_heapmember(g_dataheap, p);
+}
diff --git a/binfmt/binfmt_unloadmodule.c b/binfmt/binfmt_unloadmodule.c
index b15fc4c69c..bc5effded8 100644
--- a/binfmt/binfmt_unloadmodule.c
+++ b/binfmt/binfmt_unloadmodule.c
@@ -161,6 +161,32 @@ int unload_module(FAR struct binary_s *binp)
           file_munmap(binp->mapped, binp->mapsize);
         }
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  for (i = 0; binp->sectalloc[i] != NULL && i < binp->nsect; i++)
+    {
+#  ifdef CONFIG_ARCH_USE_TEXT_HEAP
+      if (up_textheap_heapmember(binp->sectalloc[i]))
+        {
+          up_textheap_free(binp->sectalloc[i]);
+          continue;
+        }
+#  endif
+
+#  ifdef CONFIG_ARCH_USE_DATA_HEAP
+      if (up_dataheap_heapmember(binp->sectalloc[i]))
+        {
+          up_dataheap_free(binp->sectalloc[i]);
+          continue;
+        }
+#  endif
+
+      kumm_free(binp->sectalloc[i]);
+    }
+
+  binp->alloc[0] = NULL;
+  binp->alloc[1] = NULL;
+#endif
+
       /* Free allocated address spaces */
 
       for (i = 0; i < BINFMT_NALLOC; i++)
@@ -174,6 +200,13 @@ int unload_module(FAR struct binary_s *binp)
                   up_textheap_free(binp->alloc[i]);
                 }
               else
+#endif
+#if defined(CONFIG_ARCH_USE_DATA_HEAP)
+              if (i == 1)
+                {
+                  up_dataheap_free(binp->alloc[i]);
+                }
+              else
 #endif
                 {
                   kumm_free(binp->alloc[i]);
diff --git a/binfmt/elf.c b/binfmt/elf.c
index 5e3ed98380..1ea77cea3f 100644
--- a/binfmt/elf.c
+++ b/binfmt/elf.c
@@ -164,6 +164,14 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s 
*loadinfo)
       for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
         {
           FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
+#  ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+          if (loadinfo->ehdr.e_type == ET_REL)
+            {
+              binfo("  sh_alloc:     %08jx\n",
+                    (uintmax_t)loadinfo->sectalloc[i]);
+            }
+#  endif
+
           binfo("Sections %d:\n", i);
           binfo("  sh_name:      %08x\n",  shdr->sh_name);
           binfo("  sh_type:      %08x\n",  shdr->sh_type);
@@ -317,6 +325,14 @@ static int elf_loadbinary(FAR struct binary_s *binp,
   binp->addrenv = loadinfo.addrenv;
 
 #else
+#  ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  if (loadinfo.ehdr.e_type == ET_REL)
+    {
+      binp->sectalloc = (FAR void *)loadinfo.sectalloc;
+      binp->nsect     = loadinfo.ehdr.e_shnum;
+    }
+#  endif
+
   binp->alloc[0] = (FAR void *)loadinfo.textalloc;
   binp->alloc[1] = (FAR void *)loadinfo.dataalloc;
 #  ifdef CONFIG_BINFMT_CONSTRUCTORS
diff --git a/binfmt/libelf/libelf_addrenv.c b/binfmt/libelf/libelf_addrenv.c
index 944981b408..3f2ebe3b66 100644
--- a/binfmt/libelf/libelf_addrenv.c
+++ b/binfmt/libelf/libelf_addrenv.c
@@ -146,13 +146,15 @@ errout_with_addrenv:
 
   /* Allocate memory to hold the ELF image */
 
-#  if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+#  ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
+#    if defined(CONFIG_ARCH_USE_TEXT_HEAP)
   loadinfo->textalloc = (uintptr_t)
-                        up_textheap_memalign(loadinfo->textalign, textsize);
-#  else
+                        up_textheap_memalign(loadinfo->textalign,
+                                             textsize);
+#    else
   loadinfo->textalloc = (uintptr_t)
                         kumm_memalign(loadinfo->textalign, textsize);
-#  endif
+#    endif
 
   if (!loadinfo->textalloc)
     {
@@ -161,19 +163,20 @@ errout_with_addrenv:
 
   if (loadinfo->datasize > 0)
     {
-#  if defined(CONFIG_ARCH_USE_DATA_HEAP)
+#    ifdef CONFIG_ARCH_USE_DATA_HEAP
       loadinfo->dataalloc = (uintptr_t)
                             up_dataheap_memalign(loadinfo->dataalign,
                                                  datasize);
-#  else
+#    else
       loadinfo->dataalloc = (uintptr_t)
                             kumm_memalign(loadinfo->dataalign, datasize);
-#  endif
+#    endif
       if (!loadinfo->dataalloc)
         {
           return -ENOMEM;
         }
     }
+#  endif
 
   return OK;
 #endif
@@ -290,23 +293,56 @@ void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo)
   addrenv_drop(loadinfo->addrenv, false);
 #else
 
+#  ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
   if (loadinfo->textalloc != 0)
     {
-#  if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+#    if defined(CONFIG_ARCH_USE_TEXT_HEAP)
       up_textheap_free((FAR void *)loadinfo->textalloc);
-#  else
+#    else
       kumm_free((FAR void *)loadinfo->textalloc);
-#  endif
+#    endif
     }
 
   if (loadinfo->dataalloc != 0)
     {
-#  if defined(CONFIG_ARCH_USE_DATA_HEAP)
+#    if defined(CONFIG_ARCH_USE_DATA_HEAP)
       up_dataheap_free((FAR void *)loadinfo->dataalloc);
-#  else
+#    else
       kumm_free((FAR void *)loadinfo->dataalloc);
-#  endif
+#    endif
+    }
+#  else
+  int i;
+
+  for (i = 0; loadinfo->ehdr.e_type == ET_REL && i < loadinfo->ehdr.e_shnum;
+       i++)
+    {
+      if (loadinfo->sectalloc[i] == 0)
+        {
+          continue;
+        }
+
+      if ((loadinfo->shdr[i].sh_flags & SHF_WRITE) != 0)
+        {
+#    if defined(CONFIG_ARCH_USE_DATA_HEAP)
+          up_dataheap_free((FAR void *)loadinfo->sectalloc[i]);
+#    else
+          kumm_free((FAR void *)loadinfo->sectalloc[i]);
+#    endif
+        }
+      else
+        {
+#    if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+          up_textheap_free((FAR void *)loadinfo->sectalloc[i]);
+#    else
+          kumm_free((FAR void *)loadinfo->sectalloc[i]);
+#    endif
+        }
     }
+
+    kmm_free(loadinfo->sectalloc);
+    loadinfo->sectalloc = 0;
+#  endif
 #endif
 
   /* Clear out all indications of the allocated address environment */
diff --git a/binfmt/libelf/libelf_bind.c b/binfmt/libelf/libelf_bind.c
index bd6830df92..57ec52dcb2 100644
--- a/binfmt/libelf/libelf_bind.c
+++ b/binfmt/libelf/libelf_bind.c
@@ -674,8 +674,28 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo,
    * contents to memory and invalidating the I cache).
    */
 
-  up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
-  up_coherent_dcache(loadinfo->dataalloc, loadinfo->datasize);
+  if (loadinfo->textsize > 0)
+    {
+      up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
+    }
+
+  if (loadinfo->datasize > 0)
+    {
+      up_coherent_dcache(loadinfo->dataalloc, loadinfo->datasize);
+    }
+
+#  ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  for (i = 0; loadinfo->ehdr.e_type == ET_REL && i < loadinfo->ehdr.e_shnum;
+       i++)
+    {
+      if (loadinfo->sectalloc[i] == 0)
+        {
+          continue;
+        }
+
+      up_coherent_dcache(loadinfo->sectalloc[i], loadinfo->shdr[i].sh_size);
+    }
+#  endif
 
 #endif
 
diff --git a/binfmt/libelf/libelf_load.c b/binfmt/libelf/libelf_load.c
index 408fba0991..a3d1b0d1c7 100644
--- a/binfmt/libelf/libelf_load.c
+++ b/binfmt/libelf/libelf_load.c
@@ -64,6 +64,69 @@
  * Private Functions
  ****************************************************************************/
 
+#if defined(CONFIG_ARCH_USE_SEPARATED_SECTION) && !defined(CONFIG_ARCH_ADDRENV)
+static int elf_section_alloc(FAR struct elf_loadinfo_s *loadinfo,
+                             FAR Elf_Shdr *shdr, uint8_t idx)
+{
+  if (loadinfo->ehdr.e_type != ET_REL)
+    {
+      return -EINVAL;
+    }
+
+  if (loadinfo->sectalloc == NULL)
+    {
+      /* Allocate memory info for all sections */
+
+      loadinfo->sectalloc = kmm_zalloc(sizeof(uintptr_t) *
+                                       loadinfo->ehdr.e_shnum);
+      if (loadinfo->sectalloc == NULL)
+        {
+          return -ENOMEM;
+        }
+    }
+
+  elf_sectname(loadinfo, shdr);
+  if ((shdr->sh_flags & SHF_WRITE) != 0)
+    {
+#  ifdef CONFIG_ARCH_USE_DATA_HEAP
+      loadinfo->sectalloc[idx] = (uintptr_t)
+                                 up_dataheap_memalign(
+                                   (FAR const char *)loadinfo->iobuffer,
+                                                     shdr->sh_addralign,
+                                                     shdr->sh_size);
+#  else
+      loadinfo->sectalloc[idx] = (uintptr_t)kumm_memalign(shdr->sh_addralign,
+                                                          shdr->sh_size);
+#  endif
+
+      if (loadinfo->dataalloc == 0)
+        {
+          loadinfo->dataalloc = loadinfo->sectalloc[idx];
+        }
+    }
+  else
+    {
+#  ifdef CONFIG_ARCH_USE_TEXT_HEAP
+      loadinfo->sectalloc[idx] = (uintptr_t)
+                                 up_textheap_memalign(
+                                   (FAR const char *)loadinfo->iobuffer,
+                                                     shdr->sh_addralign,
+                                                     shdr->sh_size);
+#  else
+      loadinfo->sectalloc[idx] = (uintptr_t)kumm_memalign(shdr->sh_addralign,
+                                                          shdr->sh_size);
+#  endif
+
+      if (loadinfo->textalloc == 0)
+        {
+          loadinfo->textalloc = loadinfo->sectalloc[idx];
+        }
+    }
+
+  return OK;
+}
+#endif
+
 /****************************************************************************
  * Name: elf_elfsize
  *
@@ -104,6 +167,13 @@ static void elf_elfsize(FAR struct elf_loadinfo_s 
*loadinfo)
 #endif
               )
             {
+#if defined(CONFIG_ARCH_USE_SEPARATED_SECTION) && !defined(CONFIG_ARCH_ADDRENV)
+              if (elf_section_alloc(loadinfo, shdr, i) >= 0)
+                {
+                  continue;
+                }
+#endif
+
               datasize = _ALIGN_UP(datasize, shdr->sh_addralign);
               datasize += ELF_ALIGNUP(shdr->sh_size);
               if (loadinfo->dataalign < shdr->sh_addralign)
@@ -113,6 +183,13 @@ static void elf_elfsize(FAR struct elf_loadinfo_s 
*loadinfo)
             }
           else
             {
+#if defined(CONFIG_ARCH_USE_SEPARATED_SECTION) && !defined(CONFIG_ARCH_ADDRENV)
+              if (elf_section_alloc(loadinfo, shdr, i) >= 0)
+                {
+                  continue;
+                }
+#endif
+
               textsize = _ALIGN_UP(textsize, shdr->sh_addralign);
               textsize += ELF_ALIGNUP(shdr->sh_size);
               if (loadinfo->textalign < shdr->sh_addralign)
@@ -181,7 +258,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s 
*loadinfo)
 {
   FAR uint8_t *text = (FAR uint8_t *)loadinfo->textalloc;
   FAR uint8_t *data = (FAR uint8_t *)loadinfo->dataalloc;
-  FAR uint8_t **pptr;
+  FAR uint8_t **pptr = NULL;
   int ret;
   int i;
 
@@ -193,6 +270,23 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s 
*loadinfo)
     {
       FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
 
+      /* SHF_ALLOC indicates that the section requires memory during
+       * execution.
+       */
+
+      if ((shdr->sh_flags & SHF_ALLOC) == 0)
+        {
+          continue;
+        }
+
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+      if (loadinfo->ehdr.e_type == ET_REL)
+        {
+          pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
+        }
+      else
+#endif
+
       /* SHF_WRITE indicates that the section address space is write-
        * able
        */
@@ -262,7 +356,9 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s 
*loadinfo)
           continue;
         }
 
+#ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
       *pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr, shdr->sh_addralign);
+#endif
 
       /* SHT_NOBITS indicates that there is no data in the file for the
        * section.
@@ -296,9 +392,16 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s 
*loadinfo)
 
       shdr->sh_addr = (uintptr_t)*pptr;
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+      if (loadinfo->ehdr.e_type != ET_REL)
+        {
+          *pptr += ELF_ALIGNUP(shdr->sh_size);
+        }
+#else
       /* Setup the memory pointer for the next time through the loop */
 
       *pptr += ELF_ALIGNUP(shdr->sh_size);
+#endif
     }
 
   return OK;
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index a58cf1818d..23754dea03 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -769,12 +769,17 @@ void up_extraheaps_init(void);
  * Name: up_textheap_memalign
  *
  * Description:
- *   Allocate memory for text sections with the specified alignment.
+ *   Allocate memory for text with the specified alignment and sectname.
  *
  ****************************************************************************/
 
 #if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+#  if defined(CONFIG_ARCH_USE_SEPARATED_SECTION)
+FAR void *up_textheap_memalign(FAR const char *sectname,
+                               size_t align, size_t size);
+#  else
 FAR void *up_textheap_memalign(size_t align, size_t size);
+#  endif
 #endif
 
 /****************************************************************************
@@ -849,12 +854,17 @@ void up_textheap_data_sync(void);
  * Name: up_dataheap_memalign
  *
  * Description:
- *   Allocate memory for data sections with the specified alignment.
+ *   Allocate memory for data with the specified alignment and sectname.
  *
  ****************************************************************************/
 
 #if defined(CONFIG_ARCH_USE_DATA_HEAP)
+#  if defined(CONFIG_ARCH_USE_SEPARATED_SECTION)
+FAR void *up_dataheap_memalign(FAR const char *sectname,
+                               size_t align, size_t size);
+#  else
 FAR void *up_dataheap_memalign(size_t align, size_t size);
+#  endif
 #endif
 
 /****************************************************************************
diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h
index 9fe9c47ed5..118c483627 100644
--- a/include/nuttx/binfmt/binfmt.h
+++ b/include/nuttx/binfmt/binfmt.h
@@ -69,6 +69,10 @@ struct binary_s
 
   main_t entrypt;                      /* Entry point into a program module */
   FAR void *mapped;                    /* Memory-mapped, address space */
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  FAR void **sectalloc;                /* All sections memory allocated */
+  uint16_t nsect;                      /* Number of sections */
+#endif
   FAR void *alloc[BINFMT_NALLOC];      /* Allocated address spaces */
 
 #ifdef CONFIG_BINFMT_CONSTRUCTORS
diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h
index 7c32f5ff12..0dea9ae448 100644
--- a/include/nuttx/binfmt/elf.h
+++ b/include/nuttx/binfmt/elf.h
@@ -79,6 +79,10 @@ struct elf_loadinfo_s
    * after the ELF module has been loaded.
    */
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  FAR uintptr_t     *sectalloc;   /* All sections memory allocated when ELF 
file was loaded */
+#endif
+
   uintptr_t          textalloc;  /* .text memory allocated when ELF file was 
loaded */
   uintptr_t          dataalloc;  /* .bss/.data memory allocated when ELF file 
was loaded */
   size_t             textsize;   /* Size of the ELF .text memory allocation */
diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h
index aa35b26088..8ca35e84ae 100644
--- a/include/nuttx/lib/modlib.h
+++ b/include/nuttx/lib/modlib.h
@@ -191,6 +191,10 @@ struct mod_loadinfo_s
    * after the module has been loaded.
    */
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  uintptr_t    *sectalloc;   /* All sections memory allocated when ELF file 
was loaded */
+#endif
+
   uintptr_t     textalloc;   /* .text memory allocated when module was loaded 
*/
   uintptr_t     datastart;   /* Start of.bss/.data memory in .text allocation 
*/
   size_t        textsize;    /* Size of the module .text memory allocation */
diff --git a/libs/libc/dlfcn/lib_dlopen.c b/libs/libc/dlfcn/lib_dlopen.c
index 357271ff80..a9921ccdf9 100644
--- a/libs/libc/dlfcn/lib_dlopen.c
+++ b/libs/libc/dlfcn/lib_dlopen.c
@@ -89,6 +89,14 @@ static void dldump_loadinfo(FAR struct mod_loadinfo_s 
*loadinfo)
         {
           FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
           binfo("Sections %d:\n", i);
+#    ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+          if (loadinfo->ehdr.e_type == ET_REL)
+            {
+              binfo("  sh_alloc:     %08jx\n",
+                    (uintmax_t)loadinfo->sectalloc[i]);
+            }
+#    endif
+
           binfo("  sh_name:      %08x\n", shdr->sh_name);
           binfo("  sh_type:      %08x\n", shdr->sh_type);
           binfo("  sh_flags:     %08x\n", shdr->sh_flags);
diff --git a/libs/libc/modlib/modlib_bind.c b/libs/libc/modlib/modlib_bind.c
index 33750bc7f5..6401a49dc9 100644
--- a/libs/libc/modlib/modlib_bind.c
+++ b/libs/libc/modlib/modlib_bind.c
@@ -961,8 +961,28 @@ int modlib_bind(FAR struct module_s *modp,
    * contents to memory and invalidating the I cache).
    */
 
-  up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
-  up_coherent_dcache(loadinfo->datastart, loadinfo->datasize);
+  if (loadinfo->textsize > 0)
+    {
+      up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
+    }
+
+  if (loadinfo->datasize > 0)
+    {
+      up_coherent_dcache(loadinfo->datastart, loadinfo->datasize);
+    }
+
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+  for (i = 0; loadinfo->ehdr.e_type == ET_REL && i < loadinfo->ehdr.e_shnum;
+       i++)
+    {
+      if (loadinfo->sectalloc[i] == 0)
+        {
+          continue;
+        }
+
+      up_coherent_dcache(loadinfo->sectalloc[i], loadinfo->shdr[i].sh_size);
+    }
+#endif
 
   return ret;
 }
diff --git a/libs/libc/modlib/modlib_load.c b/libs/libc/modlib/modlib_load.c
index 8e1200863f..26748ed2ae 100644
--- a/libs/libc/modlib/modlib_load.c
+++ b/libs/libc/modlib/modlib_load.c
@@ -56,6 +56,69 @@
  * Private Functions
  ****************************************************************************/
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
+                                FAR Elf_Shdr *shdr, uint8_t idx)
+{
+  if (loadinfo->ehdr.e_type != ET_REL)
+    {
+      return -EINVAL;
+    }
+
+  if (loadinfo->sectalloc == NULL)
+    {
+      /* Allocate memory info for all sections */
+
+      loadinfo->sectalloc = lib_zalloc(sizeof(uintptr_t) *
+                                      loadinfo->ehdr.e_shnum);
+      if (loadinfo->sectalloc == NULL)
+        {
+          return -ENOMEM;
+        }
+    }
+
+  modlib_sectname(loadinfo, shdr);
+  if ((shdr->sh_flags & SHF_WRITE) != 0)
+    {
+#  ifdef CONFIG_ARCH_USE_DATA_HEAP
+      loadinfo->sectalloc[idx] = (uintptr_t)
+                                 up_dataheap_memalign(
+                                   (FAR const char *)loadinfo->iobuffer,
+                                                     shdr->sh_addralign,
+                                                     shdr->sh_size);
+#  else
+      loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign,
+                                                        shdr->sh_size);
+#  endif
+
+      if (loadinfo->datastart == 0)
+        {
+          loadinfo->datastart = loadinfo->sectalloc[idx];
+        }
+    }
+  else
+    {
+#  ifdef CONFIG_ARCH_USE_TEXT_HEAP
+      loadinfo->sectalloc[idx] = (uintptr_t)
+                                 up_textheap_memalign(
+                                   (FAR const char *)loadinfo->iobuffer,
+                                                     shdr->sh_addralign,
+                                                     shdr->sh_size);
+#  else
+      loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign,
+                                                         shdr->sh_size);
+#  endif
+
+      if (loadinfo->textalloc == 0)
+        {
+          loadinfo->textalloc = loadinfo->sectalloc[idx];
+        }
+    }
+
+  return 0;
+}
+#endif
+
 /****************************************************************************
  * Name: modlib_elfsize
  *
@@ -70,7 +133,10 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s 
*loadinfo)
   size_t datasize = 0;
   int i;
 
-  /* Accumulate the size each section into memory that is marked SHF_ALLOC */
+  /* Accumulate the size each section into memory that is marked SHF_ALLOC
+   * if CONFIG_ARCH_USE_SEPARATED_SECTION is enabled, allocate
+   * (and zero) memory for the each section.
+   */
 
   if (loadinfo->ehdr.e_phnum > 0)
     {
@@ -118,6 +184,13 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s 
*loadinfo)
 #endif
                   )
                 {
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+                  if (modlib_section_alloc(loadinfo, shdr, i) >= 0)
+                    {
+                      continue;
+                    }
+#endif
+
                   datasize = _ALIGN_UP(datasize, shdr->sh_addralign);
                   datasize += ELF_ALIGNUP(shdr->sh_size);
                   if (loadinfo->dataalign < shdr->sh_addralign)
@@ -127,6 +200,13 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s 
*loadinfo)
                 }
               else
                 {
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+                  if (modlib_section_alloc(loadinfo, shdr, i) >= 0)
+                    {
+                      continue;
+                    }
+#endif
+
                   textsize = _ALIGN_UP(textsize, shdr->sh_addralign);
                   textsize += ELF_ALIGNUP(shdr->sh_size);
                   if (loadinfo->textalign < shdr->sh_addralign)
@@ -161,7 +241,6 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s 
*loadinfo)
 {
   FAR uint8_t *text = (FAR uint8_t *)loadinfo->textalloc;
   FAR uint8_t *data = (FAR uint8_t *)loadinfo->datastart;
-  FAR uint8_t **pptr;
   int ret;
   int i;
 
@@ -204,6 +283,7 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s 
*loadinfo)
       for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
         {
           FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
+          FAR uint8_t **pptr = NULL;
 
           /* SHF_ALLOC indicates that the section requires memory during
            * execution
@@ -214,25 +294,35 @@ static inline int modlib_loadfile(FAR struct 
mod_loadinfo_s *loadinfo)
               continue;
             }
 
-          /* SHF_WRITE indicates that the section address space is write-
-           * able
-           */
-
-          if ((shdr->sh_flags & SHF_WRITE) != 0
-#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
-              || (shdr->sh_flags & SHF_EXECINSTR) == 0
-#endif
-              )
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+          if (loadinfo->ehdr.e_type == ET_REL)
             {
-              pptr = &data;
+              pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
             }
-          else
+#endif
+
+          if (pptr == NULL)
             {
-              pptr = &text;
-            }
+              /* SHF_WRITE indicates that the section address space is
+               * writeable
+               */
 
-          *pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
-                                          shdr->sh_addralign);
+              if ((shdr->sh_flags & SHF_WRITE) != 0
+#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
+                  || (shdr->sh_flags & SHF_EXECINSTR) == 0
+#endif
+                  )
+                {
+                  pptr = &data;
+                }
+              else
+                {
+                  pptr = &text;
+                }
+
+              *pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
+                                           shdr->sh_addralign);
+            }
 
           /* SHT_NOBITS indicates that there is no data in the file for the
            * section.
@@ -267,9 +357,16 @@ static inline int modlib_loadfile(FAR struct 
mod_loadinfo_s *loadinfo)
 
           shdr->sh_addr = (uintptr_t)*pptr;
 
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+          if (loadinfo->ehdr.e_type != ET_REL)
+            {
+              *pptr += ELF_ALIGNUP(shdr->sh_size);
+            }
+#else
           /* Setup the memory pointer for the next time through the loop */
 
           *pptr += ELF_ALIGNUP(shdr->sh_size);
+#endif
         }
     }
 
@@ -324,18 +421,19 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
 
   if (loadinfo->ehdr.e_type == ET_REL)
     {
+#ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
       if (loadinfo->textsize > 0)
         {
-#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+#  ifdef CONFIG_ARCH_USE_TEXT_HEAP
           loadinfo->textalloc = (uintptr_t)
                                 up_textheap_memalign(loadinfo->textalign,
                                                      loadinfo->textsize +
                                                      loadinfo->segpad);
-#else
+#  else
           loadinfo->textalloc = (uintptr_t)lib_memalign(loadinfo->textalign,
                                                         loadinfo->textsize +
                                                         loadinfo->segpad);
-#endif
+#  endif
           if (!loadinfo->textalloc)
             {
               berr("ERROR: Failed to allocate memory for the module text\n");
@@ -346,14 +444,14 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
 
       if (loadinfo->datasize > 0)
         {
-#if defined(CONFIG_ARCH_USE_DATA_HEAP)
+#  ifdef CONFIG_ARCH_USE_DATA_HEAP
           loadinfo->datastart = (uintptr_t)
                                  up_dataheap_memalign(loadinfo->dataalign,
                                                       loadinfo->datasize);
-#else
+#  else
           loadinfo->datastart = (uintptr_t)lib_memalign(loadinfo->dataalign,
                                                         loadinfo->datasize);
-#endif
+#  endif
           if (!loadinfo->datastart)
             {
               berr("ERROR: Failed to allocate memory for the module data\n");
@@ -361,6 +459,7 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
               goto errout_with_buffers;
             }
         }
+#endif
     }
   else
     {
diff --git a/libs/libc/modlib/modlib_unload.c b/libs/libc/modlib/modlib_unload.c
index ebd88404de..02c8646855 100644
--- a/libs/libc/modlib/modlib_unload.c
+++ b/libs/libc/modlib/modlib_unload.c
@@ -62,6 +62,33 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
 
   if (loadinfo->ehdr.e_type != ET_DYN)
     {
+#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+      int i;
+
+      for (i = 0; loadinfo->sectalloc[i] != 0 &&
+                  i < loadinfo->ehdr.e_shnum; i++)
+        {
+#  ifdef CONFIG_ARCH_USE_TEXT_HEAP
+          if (up_textheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
+            {
+              up_textheap_free((FAR void *)loadinfo->sectalloc[i]);
+              continue;
+            }
+#  endif
+
+#  ifdef CONFIG_ARCH_USE_DATA_HEAP
+          if (up_dataheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
+            {
+              up_dataheap_free((FAR void *)loadinfo->sectalloc[i]);
+              continue;
+            }
+#  endif
+
+          lib_free((FAR void *)loadinfo->sectalloc[i]);
+        }
+
+    lib_free(loadinfo->sectalloc);
+#else
       if (loadinfo->textalloc != 0)
         {
 #if defined(CONFIG_ARCH_USE_TEXT_HEAP)
@@ -79,6 +106,7 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
           lib_free((FAR void *)loadinfo->datastart);
 #endif
         }
+#endif
     }
   else
     {
diff --git a/sched/module/mod_insmod.c b/sched/module/mod_insmod.c
index 25539f381b..a020089450 100644
--- a/sched/module/mod_insmod.c
+++ b/sched/module/mod_insmod.c
@@ -90,6 +90,14 @@ static void mod_dumploadinfo(FAR struct mod_loadinfo_s 
*loadinfo)
         {
           FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
           binfo("Sections %d:\n", i);
+#  ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
+          if (loadinfo->ehdr.e_type == ET_REL)
+            {
+              binfo("  sh_alloc:     %08jx\n",
+                    (uintmax_t)loadinfo->sectalloc[i]);
+            }
+#  endif
+
           binfo("  sh_name:      %08x\n",  shdr->sh_name);
           binfo("  sh_type:      %08x\n",  shdr->sh_type);
           binfo("  sh_flags:     %08jx\n", (uintmax_t)shdr->sh_flags);

Reply via email to