modlib:if elf in romfs/tmpfs, try use xipbase

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2024-07-03 19:45:27 +08:00 committed by GUIDINGLI
parent 112b6fd9a5
commit a72e9e5621
5 changed files with 63 additions and 9 deletions

View File

@ -160,6 +160,10 @@ struct module_s
struct mod_info_s modinfo; /* Module information */
FAR void *textalloc; /* Allocated kernel text memory */
FAR void *dataalloc; /* Allocated kernel memory */
uintptr_t xipbase; /* if elf is position independent, and use
* romfs/tmps, we can try get xipbase,
* skip the copy.
*/
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
FAR void **sectalloc; /* All sections memory allocated when ELF file was loaded */
uint16_t nsect; /* Number of entries in sectalloc array */
@ -232,6 +236,10 @@ struct mod_loadinfo_s
int filfd; /* Descriptor for the file being loaded */
int nexports; /* ET_DYN - Number of symbols exported */
int gotindex; /* Index to the GOT section */
uintptr_t xipbase; /* if elf is position independent, and use
* romfs/tmps, we can try get xipbase,
* skip the copy.
*/
/* Address environment.
*

View File

@ -1045,6 +1045,8 @@ int modlib_bind(FAR struct module_s *modp,
}
}
modp->xipbase = loadinfo->xipbase;
/* Ensure that the I and D caches are coherent before starting the newly
* loaded module by cleaning the D cache (i.e., flushing the D cache
* contents to memory and invalidating the I cache).

View File

@ -32,12 +32,14 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/lib/modlib.h>
#include <nuttx/fs/ioctl.h>
#include "libc.h"
#include "modlib/modlib.h"
@ -62,7 +64,7 @@
static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, uint8_t idx)
{
if (loadinfo->ehdr.e_type != ET_DYN)
if (loadinfo->ehdr.e_type == ET_DYN)
{
return -EINVAL;
}
@ -98,6 +100,14 @@ static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
loadinfo->datastart = loadinfo->sectalloc[idx];
}
}
else if (loadinfo->xipbase != 0)
{
loadinfo->sectalloc[idx] = loadinfo->xipbase + shdr->sh_offset;
if (loadinfo->textalloc == 0)
{
loadinfo->textalloc = loadinfo->sectalloc[idx];
}
}
else
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
@ -107,8 +117,9 @@ static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign,
shdr->sh_size);
loadinfo->sectalloc[idx] = (uintptr_t)
lib_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->textalloc == 0)
@ -365,8 +376,20 @@ 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);
if (loadinfo->xipbase == 0)
{
/* If xipbase is not set, align the address
* xipbase is set, the address can't be aligned
*/
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
shdr->sh_addralign);
}
}
if ((shdr->sh_flags & SHF_WRITE) == 0 && loadinfo->xipbase != 0)
{
goto skipload;
}
/* SHT_NOBITS indicates that there is no data in the file for the
@ -406,6 +429,8 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
}
#endif
skipload:
/* Update sh_addr to point to copy in memory */
binfo("%d. %08lx->%08lx\n", i,
@ -497,6 +522,11 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->gotindex >= 0)
{
binfo("GOT section found! index %d\n", loadinfo->gotindex);
if (ioctl(loadinfo->filfd, FIOC_XIPBASE,
(unsigned long)&loadinfo->xipbase) >= 0)
{
binfo("can use xipbase %zu\n", loadinfo->xipbase);
}
}
/* Determine total size to allocate */
@ -517,7 +547,12 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->ehdr.e_type == ET_REL || loadinfo->ehdr.e_type == ET_EXEC)
{
# ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->textsize > 0)
if (loadinfo->xipbase != 0)
{
loadinfo->textalloc = loadinfo->xipbase +
loadinfo->shdr[1].sh_offset;
}
else if (loadinfo->textsize > 0)
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->textalloc = (uintptr_t)
@ -643,6 +678,11 @@ int modlib_load_with_addrenv(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->gotindex >= 0)
{
binfo("GOT section found! index %d\n", loadinfo->gotindex);
if (ioctl(loadinfo->filfd, FIOC_XIPBASE,
(unsigned long)&loadinfo->xipbase) >= 0)
{
binfo("can use xipbase %zu\n", loadinfo->xipbase);
}
}
/* Determine total size to allocate */

View File

@ -132,11 +132,15 @@ int modlib_uninit(FAR struct module_s *modp)
modp->sectalloc = NULL;
modp->nsect = 0;
#else
if (modp->xipbase == 0)
{
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)modp->textalloc);
up_textheap_free((FAR void *)modp->textalloc);
# else
lib_free((FAR void *)modp->textalloc);
lib_free((FAR void *)modp->textalloc);
# endif
}
# if defined(CONFIG_ARCH_USE_DATA_HEAP)
up_dataheap_free((FAR void *)modp->dataalloc);
# else

View File

@ -99,7 +99,7 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
lib_free(loadinfo->sectalloc);
#else
if (loadinfo->textalloc != 0)
if (loadinfo->textalloc != 0 && loadinfo->xipbase == 0)
{
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)loadinfo->textalloc);