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:
parent
6e746ed364
commit
1f1d90de1c
|
@ -671,6 +671,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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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]);
|
||||
|
|
16
binfmt/elf.c
16
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -771,12 +771,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
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -851,12 +856,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
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -964,8 +964,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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||
if (loadinfo->ehdr.e_type == ET_REL)
|
||||
{
|
||||
pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
|
||||
}
|
||||
#endif
|
||||
)
|
||||
{
|
||||
pptr = &data;
|
||||
}
|
||||
else
|
||||
{
|
||||
pptr = &text;
|
||||
}
|
||||
|
||||
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
|
||||
shdr->sh_addralign);
|
||||
if (pptr == NULL)
|
||||
{
|
||||
/* 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
|
||||
* 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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue