binfmt/libelf: Implement sh_addralign handling

Basically, mirror the following two commits from modlib.
It's shame we have two copies of elf loaders.

```
commit 51490bad55
Author: 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)
```

```
commit 418e11b8b3
Author: 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:
YAMAMOTO Takashi 2022-01-28 15:13:41 +09:00 committed by Xiang Xiao
parent 764fc7ef5e
commit e596d5bd5e
4 changed files with 33 additions and 21 deletions

View file

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

View file

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

View file

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

View file

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