binfmt/libelf: Implement sh_addralign handling
Basically, mirror the following two commits from modlib. It's shame we have two copies of elf loaders. ``` commit51490bad55Author: YAMAMOTO Takashi <yamamoto@midokura.com> Date: Wed Apr 14 17:07:39 2021 +0900 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) ``` ``` commit418e11b8b3Author: YAMAMOTO Takashi <yamamoto@midokura.com> Date: Thu Apr 15 11:33:48 2021 +0900 modlib: Always use separate allocation for text and data Pros: * Reduce code differences * Smaller allocations for !CONFIG_ARCH_USE_MODULE_TEXT Cons: * Likely to use more memory for !CONFIG_ARCH_USE_MODULE_TEXT in total Tested with: * sim:module on macOS * esp32-devkit:nsh + CONFIG_MODULE on qemu * lm3s6965-ek:qemu-protected + CONFIG_EXAMPLES_SOTEST on qemu ```
This commit is contained in:
parent
764fc7ef5e
commit
e596d5bd5e
4 changed files with 33 additions and 21 deletions
|
|
@ -112,6 +112,8 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
|
|||
binfo(" dataalloc: %08lx\n", (long)loadinfo->dataalloc);
|
||||
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);
|
||||
#ifdef CONFIG_BINFMT_CONSTRUCTORS
|
||||
binfo(" ctoralloc: %08lx\n", (long)loadinfo->ctoralloc);
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
|
|||
up_textheap_memalign(loadinfo->textalign,
|
||||
textsize);
|
||||
#else
|
||||
loadinfo->textalloc = (uintptr_t)kumm_malloc(textsize + datasize);
|
||||
loadinfo->textalloc = (uintptr_t)kumm_memalign(loadinfo->textalign,
|
||||
textsize);
|
||||
#endif
|
||||
|
||||
if (!loadinfo->textalloc)
|
||||
|
|
@ -130,16 +131,15 @@ int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
loadinfo->dataalloc = (uintptr_t)kumm_malloc(datasize);
|
||||
|
||||
if (0 != datasize && !loadinfo->dataalloc)
|
||||
if (loadinfo->datasize > 0)
|
||||
{
|
||||
return -ENOMEM;
|
||||
loadinfo->dataalloc = (uintptr_t)kumm_memalign(loadinfo->dataalign,
|
||||
datasize);
|
||||
if (!loadinfo->dataalloc)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
#else
|
||||
loadinfo->dataalloc = loadinfo->textalloc + textsize;
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
#endif
|
||||
|
|
@ -177,24 +177,19 @@ void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo)
|
|||
}
|
||||
#else
|
||||
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
if (loadinfo->textalloc != 0)
|
||||
{
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
up_textheap_free((FAR void *)loadinfo->textalloc);
|
||||
#else
|
||||
kumm_free((FAR void *)loadinfo->textalloc);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (loadinfo->dataalloc != 0)
|
||||
{
|
||||
kumm_free((FAR void *)loadinfo->dataalloc);
|
||||
}
|
||||
#else
|
||||
/* If there is an allocation for the ELF image, free it */
|
||||
|
||||
if (loadinfo->textalloc != 0)
|
||||
{
|
||||
kumm_free((FAR void *)loadinfo->textalloc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,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 Constant Data
|
||||
****************************************************************************/
|
||||
|
|
@ -104,11 +108,21 @@ static void elf_elfsize(struct elf_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -172,6 +186,8 @@ static inline int elf_loadfile(FAR struct elf_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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -95,10 +95,9 @@ struct elf_loadinfo_s
|
|||
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 */
|
||||
#ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
||||
size_t textalign; /* Necessary alignment of .text */
|
||||
#endif
|
||||
size_t datasize; /* Size of the ELF .bss/.data memory allocation */
|
||||
size_t textalign; /* Necessary alignment of .text */
|
||||
size_t dataalign; /* Necessary alignment of .bss/.data */
|
||||
off_t filelen; /* Length of the entire ELF file */
|
||||
|
||||
Elf_Ehdr ehdr; /* Buffered ELF file header */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue