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 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2023-11-29 22:25:47 +08:00 committed by Xiang Xiao
parent a965e3c3f9
commit 3b0e2be058
18 changed files with 507 additions and 48 deletions

View File

@ -670,6 +670,14 @@ config ARCH_USE_DATA_HEAP
This option enables architecture-specific memory allocator This option enables architecture-specific memory allocator
for dynamic data loading. 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 menuconfig ARCH_ADDRENV
bool "Address environments" bool "Address environments"
default n default n

View File

@ -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_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_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_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 CSRCS += sim_checkhostfstypes.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y) ifeq ($(CONFIG_SCHED_BACKTRACE),y)

View File

@ -57,7 +57,7 @@ list(
sim_registerdump.c sim_registerdump.c
sim_saveusercontext.c sim_saveusercontext.c
sim_tcbinfo.c sim_tcbinfo.c
sim_textheap.c sim_sectionheap.c
sim_checkhostfstypes.c) sim_checkhostfstypes.c)
if(CONFIG_HOST_X86_64) if(CONFIG_HOST_X86_64)

View File

@ -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 * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * 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_textheap;
static struct mm_heap_s *g_dataheap;
/**************************************************************************** /****************************************************************************
* Public Functions * 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) void *up_textheap_memalign(size_t align, size_t size)
#endif
{ {
if (g_textheap == NULL) if (g_textheap == NULL)
{ {
@ -85,3 +90,56 @@ bool up_textheap_heapmember(void *p)
{ {
return g_textheap != NULL && mm_heapmember(g_textheap, 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);
}

View File

@ -161,6 +161,32 @@ int unload_module(FAR struct binary_s *binp)
file_munmap(binp->mapped, binp->mapsize); 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 */ /* Free allocated address spaces */
for (i = 0; i < BINFMT_NALLOC; i++) 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]); up_textheap_free(binp->alloc[i]);
} }
else else
#endif
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
if (i == 1)
{
up_dataheap_free(binp->alloc[i]);
}
else
#endif #endif
{ {
kumm_free(binp->alloc[i]); kumm_free(binp->alloc[i]);

View File

@ -164,6 +164,14 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
for (i = 0; i < loadinfo->ehdr.e_shnum; i++) for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{ {
FAR Elf_Shdr *shdr = &loadinfo->shdr[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("Sections %d:\n", i);
binfo(" sh_name: %08x\n", shdr->sh_name); binfo(" sh_name: %08x\n", shdr->sh_name);
binfo(" sh_type: %08x\n", shdr->sh_type); 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; binp->addrenv = loadinfo.addrenv;
#else #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[0] = (FAR void *)loadinfo.textalloc;
binp->alloc[1] = (FAR void *)loadinfo.dataalloc; binp->alloc[1] = (FAR void *)loadinfo.dataalloc;
# ifdef CONFIG_BINFMT_CONSTRUCTORS # ifdef CONFIG_BINFMT_CONSTRUCTORS

View File

@ -146,13 +146,15 @@ errout_with_addrenv:
/* Allocate memory to hold the ELF image */ /* 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) loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign, textsize); up_textheap_memalign(loadinfo->textalign,
# else textsize);
# else
loadinfo->textalloc = (uintptr_t) loadinfo->textalloc = (uintptr_t)
kumm_memalign(loadinfo->textalign, textsize); kumm_memalign(loadinfo->textalign, textsize);
# endif # endif
if (!loadinfo->textalloc) if (!loadinfo->textalloc)
{ {
@ -161,19 +163,20 @@ errout_with_addrenv:
if (loadinfo->datasize > 0) if (loadinfo->datasize > 0)
{ {
# if defined(CONFIG_ARCH_USE_DATA_HEAP) # ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->dataalloc = (uintptr_t) loadinfo->dataalloc = (uintptr_t)
up_dataheap_memalign(loadinfo->dataalign, up_dataheap_memalign(loadinfo->dataalign,
datasize); datasize);
# else # else
loadinfo->dataalloc = (uintptr_t) loadinfo->dataalloc = (uintptr_t)
kumm_memalign(loadinfo->dataalign, datasize); kumm_memalign(loadinfo->dataalign, datasize);
# endif # endif
if (!loadinfo->dataalloc) if (!loadinfo->dataalloc)
{ {
return -ENOMEM; return -ENOMEM;
} }
} }
# endif
return OK; return OK;
#endif #endif
@ -290,23 +293,56 @@ void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo)
addrenv_drop(loadinfo->addrenv, false); addrenv_drop(loadinfo->addrenv, false);
#else #else
# ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->textalloc != 0) 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); up_textheap_free((FAR void *)loadinfo->textalloc);
# else # else
kumm_free((FAR void *)loadinfo->textalloc); kumm_free((FAR void *)loadinfo->textalloc);
# endif # endif
} }
if (loadinfo->dataalloc != 0) 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); up_dataheap_free((FAR void *)loadinfo->dataalloc);
# else # else
kumm_free((FAR void *)loadinfo->dataalloc); 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 #endif
/* Clear out all indications of the allocated address environment */ /* Clear out all indications of the allocated address environment */

View File

@ -674,8 +674,28 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo,
* contents to memory and invalidating the I cache). * contents to memory and invalidating the I cache).
*/ */
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize); if (loadinfo->textsize > 0)
up_coherent_dcache(loadinfo->dataalloc, loadinfo->datasize); {
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 #endif

View File

@ -64,6 +64,69 @@
* Private Functions * 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 * Name: elf_elfsize
* *
@ -104,6 +167,13 @@ static void elf_elfsize(FAR struct elf_loadinfo_s *loadinfo)
#endif #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 = _ALIGN_UP(datasize, shdr->sh_addralign);
datasize += ELF_ALIGNUP(shdr->sh_size); datasize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->dataalign < shdr->sh_addralign) if (loadinfo->dataalign < shdr->sh_addralign)
@ -113,6 +183,13 @@ static void elf_elfsize(FAR struct elf_loadinfo_s *loadinfo)
} }
else 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 = _ALIGN_UP(textsize, shdr->sh_addralign);
textsize += ELF_ALIGNUP(shdr->sh_size); textsize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->textalign < shdr->sh_addralign) 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 *text = (FAR uint8_t *)loadinfo->textalloc;
FAR uint8_t *data = (FAR uint8_t *)loadinfo->dataalloc; FAR uint8_t *data = (FAR uint8_t *)loadinfo->dataalloc;
FAR uint8_t **pptr; FAR uint8_t **pptr = NULL;
int ret; int ret;
int i; int i;
@ -193,6 +270,23 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
{ {
FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; 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- /* SHF_WRITE indicates that the section address space is write-
* able * able
*/ */
@ -262,7 +356,9 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
continue; continue;
} }
#ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr, shdr->sh_addralign); *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 /* SHT_NOBITS indicates that there is no data in the file for the
* section. * section.
@ -296,9 +392,16 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
shdr->sh_addr = (uintptr_t)*pptr; 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 */ /* Setup the memory pointer for the next time through the loop */
*pptr += ELF_ALIGNUP(shdr->sh_size); *pptr += ELF_ALIGNUP(shdr->sh_size);
#endif
} }
return OK; return OK;

View File

@ -769,12 +769,17 @@ void up_extraheaps_init(void);
* Name: up_textheap_memalign * Name: up_textheap_memalign
* *
* Description: * 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_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); FAR void *up_textheap_memalign(size_t align, size_t size);
# endif
#endif #endif
/**************************************************************************** /****************************************************************************
@ -849,12 +854,17 @@ void up_textheap_data_sync(void);
* Name: up_dataheap_memalign * Name: up_dataheap_memalign
* *
* Description: * 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_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); FAR void *up_dataheap_memalign(size_t align, size_t size);
# endif
#endif #endif
/**************************************************************************** /****************************************************************************

View File

@ -69,6 +69,10 @@ struct binary_s
main_t entrypt; /* Entry point into a program module */ main_t entrypt; /* Entry point into a program module */
FAR void *mapped; /* Memory-mapped, address space */ 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 */ FAR void *alloc[BINFMT_NALLOC]; /* Allocated address spaces */
#ifdef CONFIG_BINFMT_CONSTRUCTORS #ifdef CONFIG_BINFMT_CONSTRUCTORS

View File

@ -79,6 +79,10 @@ struct elf_loadinfo_s
* after the ELF module has been loaded. * 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 textalloc; /* .text memory allocated when ELF file was loaded */
uintptr_t dataalloc; /* .bss/.data 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 */ size_t textsize; /* Size of the ELF .text memory allocation */

View File

@ -191,6 +191,10 @@ struct mod_loadinfo_s
* after the module has been loaded. * 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 textalloc; /* .text memory allocated when module was loaded */
uintptr_t datastart; /* Start of.bss/.data memory in .text allocation */ uintptr_t datastart; /* Start of.bss/.data memory in .text allocation */
size_t textsize; /* Size of the module .text memory allocation */ size_t textsize; /* Size of the module .text memory allocation */

View File

@ -89,6 +89,14 @@ static void dldump_loadinfo(FAR struct mod_loadinfo_s *loadinfo)
{ {
FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
binfo("Sections %d:\n", 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_name: %08x\n", shdr->sh_name);
binfo(" sh_type: %08x\n", shdr->sh_type); binfo(" sh_type: %08x\n", shdr->sh_type);
binfo(" sh_flags: %08x\n", shdr->sh_flags); binfo(" sh_flags: %08x\n", shdr->sh_flags);

View File

@ -961,8 +961,28 @@ int modlib_bind(FAR struct module_s *modp,
* contents to memory and invalidating the I cache). * contents to memory and invalidating the I cache).
*/ */
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize); if (loadinfo->textsize > 0)
up_coherent_dcache(loadinfo->datastart, loadinfo->datasize); {
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; return ret;
} }

View File

@ -56,6 +56,69 @@
* Private Functions * 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 * Name: modlib_elfsize
* *
@ -70,7 +133,10 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s *loadinfo)
size_t datasize = 0; size_t datasize = 0;
int i; 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) if (loadinfo->ehdr.e_phnum > 0)
{ {
@ -118,6 +184,13 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s *loadinfo)
#endif #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 = _ALIGN_UP(datasize, shdr->sh_addralign);
datasize += ELF_ALIGNUP(shdr->sh_size); datasize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->dataalign < shdr->sh_addralign) if (loadinfo->dataalign < shdr->sh_addralign)
@ -127,6 +200,13 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s *loadinfo)
} }
else 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 = _ALIGN_UP(textsize, shdr->sh_addralign);
textsize += ELF_ALIGNUP(shdr->sh_size); textsize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->textalign < shdr->sh_addralign) 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 *text = (FAR uint8_t *)loadinfo->textalloc;
FAR uint8_t *data = (FAR uint8_t *)loadinfo->datastart; FAR uint8_t *data = (FAR uint8_t *)loadinfo->datastart;
FAR uint8_t **pptr;
int ret; int ret;
int i; 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++) for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{ {
FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
FAR uint8_t **pptr = NULL;
/* SHF_ALLOC indicates that the section requires memory during /* SHF_ALLOC indicates that the section requires memory during
* execution * execution
@ -214,25 +294,35 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
continue; continue;
} }
/* SHF_WRITE indicates that the section address space is write- #ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
* able if (loadinfo->ehdr.e_type == ET_REL)
*/ {
pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
if ((shdr->sh_flags & SHF_WRITE) != 0 }
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif #endif
)
{
pptr = &data;
}
else
{
pptr = &text;
}
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr, if (pptr == NULL)
shdr->sh_addralign); {
/* SHF_WRITE indicates that the section address space is
* writeable
*/
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 /* SHT_NOBITS indicates that there is no data in the file for the
* section. * section.
@ -267,9 +357,16 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
shdr->sh_addr = (uintptr_t)*pptr; 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 */ /* Setup the memory pointer for the next time through the loop */
*pptr += ELF_ALIGNUP(shdr->sh_size); *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) if (loadinfo->ehdr.e_type == ET_REL)
{ {
#ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->textsize > 0) if (loadinfo->textsize > 0)
{ {
#if defined(CONFIG_ARCH_USE_TEXT_HEAP) # ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->textalloc = (uintptr_t) loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign, up_textheap_memalign(loadinfo->textalign,
loadinfo->textsize + loadinfo->textsize +
loadinfo->segpad); loadinfo->segpad);
#else # else
loadinfo->textalloc = (uintptr_t)lib_memalign(loadinfo->textalign, loadinfo->textalloc = (uintptr_t)lib_memalign(loadinfo->textalign,
loadinfo->textsize + loadinfo->textsize +
loadinfo->segpad); loadinfo->segpad);
#endif # endif
if (!loadinfo->textalloc) if (!loadinfo->textalloc)
{ {
berr("ERROR: Failed to allocate memory for the module text\n"); 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 (loadinfo->datasize > 0)
{ {
#if defined(CONFIG_ARCH_USE_DATA_HEAP) # ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->datastart = (uintptr_t) loadinfo->datastart = (uintptr_t)
up_dataheap_memalign(loadinfo->dataalign, up_dataheap_memalign(loadinfo->dataalign,
loadinfo->datasize); loadinfo->datasize);
#else # else
loadinfo->datastart = (uintptr_t)lib_memalign(loadinfo->dataalign, loadinfo->datastart = (uintptr_t)lib_memalign(loadinfo->dataalign,
loadinfo->datasize); loadinfo->datasize);
#endif # endif
if (!loadinfo->datastart) if (!loadinfo->datastart)
{ {
berr("ERROR: Failed to allocate memory for the module data\n"); 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; goto errout_with_buffers;
} }
} }
#endif
} }
else else
{ {

View File

@ -62,6 +62,33 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->ehdr.e_type != ET_DYN) 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 (loadinfo->textalloc != 0)
{ {
#if defined(CONFIG_ARCH_USE_TEXT_HEAP) #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); lib_free((FAR void *)loadinfo->datastart);
#endif #endif
} }
#endif
} }
else else
{ {

View File

@ -90,6 +90,14 @@ static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
{ {
FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
binfo("Sections %d:\n", 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_name: %08x\n", shdr->sh_name);
binfo(" sh_type: %08x\n", shdr->sh_type); binfo(" sh_type: %08x\n", shdr->sh_type);
binfo(" sh_flags: %08jx\n", (uintmax_t)shdr->sh_flags); binfo(" sh_flags: %08jx\n", (uintmax_t)shdr->sh_flags);