modlib: Implement sh_addralign handling

I've seen a module with 16 bytes .rodata alignment for xmm operations.
It was getting SEGV on sim/Linux because of the alignment issue.
The same module binary seems working fine after applying this patch.

Also, tested on sim/macOS and esp32 on qemu,
using a module with an artificially large alignment. (64 bytes)
This commit is contained in:
YAMAMOTO Takashi 2021-04-14 17:07:39 +09:00 committed by Xiang Xiao
parent 7813b4f88a
commit 51490bad55
5 changed files with 51 additions and 12 deletions

View File

@ -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);
}
/****************************************************************************

View File

@ -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
/****************************************************************************

View File

@ -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 */

View File

@ -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 */

View File

@ -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);