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:
parent
7813b4f88a
commit
51490bad55
|
@ -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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue