diff --git a/arch/xtensa/src/esp32/esp32_modtext.c b/arch/xtensa/src/esp32/esp32_modtext.c index 8558661612..2c738d45f6 100644 --- a/arch/xtensa/src/esp32/esp32_modtext.c +++ b/arch/xtensa/src/esp32/esp32_modtext.c @@ -70,16 +70,16 @@ void up_module_text_init() } /**************************************************************************** - * Name: up_module_text_alloc + * Name: up_module_text_memalign * * Description: - * Allocate memory for module text. + * Allocate memory for module text with the specified alignment. * ****************************************************************************/ -FAR void *up_module_text_alloc(size_t size) +FAR void *up_module_text_memalign(size_t align, size_t size) { - return mm_malloc(&g_module_text, size); + return mm_memalign(&g_module_text, align, size); } /**************************************************************************** diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 3697f93a1c..379146e51a 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -730,15 +730,15 @@ void up_module_text_init(void); #endif /**************************************************************************** - * Name: up_module_text_alloc + * Name: up_module_text_memalign * * Description: - * Allocate memory for module text. + * Allocate memory for module text with the specified alignment. * ****************************************************************************/ #if defined(CONFIG_ARCH_USE_MODULE_TEXT) -FAR void *up_module_text_alloc(size_t size); +FAR void *up_module_text_memalign(size_t align, size_t size); #endif /**************************************************************************** diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h index efe8dd19e0..bd2b3631de 100644 --- a/include/nuttx/lib/modlib.h +++ b/include/nuttx/lib/modlib.h @@ -198,6 +198,8 @@ struct mod_loadinfo_s uintptr_t datastart; /* Start of.bss/.data memory in .text allocation */ size_t textsize; /* Size of the module .text memory allocation */ size_t datasize; /* Size of the module .bss/.data memory allocation */ + size_t textalign; /* Necessary alignment of .text */ + size_t dataalign; /* Necessary alignment of .bss/.text */ off_t filelen; /* Length of the entire module file */ Elf_Ehdr ehdr; /* Buffered module file header */ FAR Elf_Shdr *shdr; /* Buffered module section headers */ diff --git a/libs/libc/modlib/modlib_load.c b/libs/libc/modlib/modlib_load.c index 206f852f4b..839e9d0414 100644 --- a/libs/libc/modlib/modlib_load.c +++ b/libs/libc/modlib/modlib_load.c @@ -55,6 +55,10 @@ # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif +/* _ALIGN_UP: 'a' is assumed to be a power of two */ + +#define _ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1)) + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -98,11 +102,21 @@ static void modlib_elfsize(struct mod_loadinfo_s *loadinfo) if ((shdr->sh_flags & SHF_WRITE) != 0) { + datasize = _ALIGN_UP(datasize, shdr->sh_addralign); datasize += ELF_ALIGNUP(shdr->sh_size); + if (loadinfo->dataalign < shdr->sh_addralign) + { + loadinfo->dataalign = shdr->sh_addralign; + } } else { + textsize = _ALIGN_UP(textsize, shdr->sh_addralign); textsize += ELF_ALIGNUP(shdr->sh_size); + if (loadinfo->textalign < shdr->sh_addralign) + { + loadinfo->textalign = shdr->sh_addralign; + } } } } @@ -166,6 +180,8 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo) 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. */ @@ -225,6 +241,10 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo) int modlib_load(FAR struct mod_loadinfo_s *loadinfo) { +#if !defined(CONFIG_ARCH_USE_MODULE_TEXT) + size_t align; + size_t text_size; +#endif int ret; binfo("loadinfo: %p\n", loadinfo); @@ -251,7 +271,8 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo) if (loadinfo->textsize > 0) { loadinfo->textalloc = (uintptr_t) - up_module_text_alloc(loadinfo->textsize); + up_module_text_memalign(loadinfo->textalign, + loadinfo->textsize); if (!loadinfo->textalloc) { berr("ERROR: Failed to allocate memory for the module text\n"); @@ -262,7 +283,8 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo) if (loadinfo->datasize > 0) { - loadinfo->datastart = (uintptr_t)lib_malloc(loadinfo->datasize); + loadinfo->datastart = (uintptr_t)lib_memalign(loadinfo->dataalign, + loadinfo->datasize); if (!loadinfo->datastart) { berr("ERROR: Failed to allocate memory for the module data\n"); @@ -271,8 +293,21 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo) } } #else - loadinfo->textalloc = (uintptr_t)lib_malloc(loadinfo->textsize + - loadinfo->datasize); + align = loadinfo->textalign; + if (align < loadinfo->dataalign) + { + align = loadinfo->dataalign; + } + + text_size = loadinfo->textsize; + if (loadinfo->datasize > 0) + { + text_size = _ALIGN_UP(text_size, loadinfo->dataalign); + } + + loadinfo->textalloc = (uintptr_t)lib_memalign(align, + text_size + + loadinfo->datasize); if (!loadinfo->textalloc) { berr("ERROR: Failed to allocate memory for the module\n"); @@ -280,7 +315,7 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo) goto errout_with_buffers; } - loadinfo->datastart = loadinfo->textalloc + loadinfo->textsize; + loadinfo->datastart = loadinfo->textalloc + text_size; #endif /* Load ELF section data into memory */ diff --git a/sched/module/mod_insmod.c b/sched/module/mod_insmod.c index 7cc6f3a3ae..a90c455f58 100644 --- a/sched/module/mod_insmod.c +++ b/sched/module/mod_insmod.c @@ -64,6 +64,8 @@ static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo) binfo(" datastart: %08lx\n", (long)loadinfo->datastart); binfo(" textsize: %ld\n", (long)loadinfo->textsize); binfo(" datasize: %ld\n", (long)loadinfo->datasize); + binfo(" textalign: %zu\n", loadinfo->textalign); + binfo(" dataalign: %zu\n", loadinfo->dataalign); binfo(" filelen: %ld\n", (long)loadinfo->filelen); binfo(" filfd: %d\n", loadinfo->filfd); binfo(" symtabidx: %d\n", loadinfo->symtabidx);