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
+8
View File
@@ -160,6 +160,10 @@ struct module_s
struct mod_info_s modinfo; /* Module information */ struct mod_info_s modinfo; /* Module information */
FAR void *textalloc; /* Allocated kernel text memory */ FAR void *textalloc; /* Allocated kernel text memory */
FAR void *dataalloc; /* Allocated kernel 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 #ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
FAR void **sectalloc; /* All sections memory allocated when ELF file was loaded */ FAR void **sectalloc; /* All sections memory allocated when ELF file was loaded */
uint16_t nsect; /* Number of entries in sectalloc array */ 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 filfd; /* Descriptor for the file being loaded */
int nexports; /* ET_DYN - Number of symbols exported */ int nexports; /* ET_DYN - Number of symbols exported */
int gotindex; /* Index to the GOT section */ 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. /* Address environment.
* *
+2
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 /* 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 * loaded module by cleaning the D cache (i.e., flushing the D cache
* contents to memory and invalidating the I cache). * contents to memory and invalidating the I cache).
+46 -6
View File
@@ -32,12 +32,14 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/lib/modlib.h> #include <nuttx/lib/modlib.h>
#include <nuttx/fs/ioctl.h>
#include "libc.h" #include "libc.h"
#include "modlib/modlib.h" #include "modlib/modlib.h"
@@ -62,7 +64,7 @@
static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo, static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, uint8_t idx) FAR Elf_Shdr *shdr, uint8_t idx)
{ {
if (loadinfo->ehdr.e_type != ET_DYN) if (loadinfo->ehdr.e_type == ET_DYN)
{ {
return -EINVAL; return -EINVAL;
} }
@@ -98,6 +100,14 @@ static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
loadinfo->datastart = loadinfo->sectalloc[idx]; 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 else
{ {
# ifdef CONFIG_ARCH_USE_TEXT_HEAP # 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_addralign,
shdr->sh_size); shdr->sh_size);
# else # else
loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign, loadinfo->sectalloc[idx] = (uintptr_t)
shdr->sh_size); lib_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif # endif
if (loadinfo->textalloc == 0) if (loadinfo->textalloc == 0)
@@ -365,8 +376,20 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
pptr = &text; pptr = &text;
} }
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr, if (loadinfo->xipbase == 0)
shdr->sh_addralign); {
/* 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 /* 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 #endif
skipload:
/* Update sh_addr to point to copy in memory */ /* Update sh_addr to point to copy in memory */
binfo("%d. %08lx->%08lx\n", i, binfo("%d. %08lx->%08lx\n", i,
@@ -497,6 +522,11 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->gotindex >= 0) if (loadinfo->gotindex >= 0)
{ {
binfo("GOT section found! index %d\n", loadinfo->gotindex); 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 */ /* 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) if (loadinfo->ehdr.e_type == ET_REL || loadinfo->ehdr.e_type == ET_EXEC)
{ {
# ifndef CONFIG_ARCH_USE_SEPARATED_SECTION # 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 # ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->textalloc = (uintptr_t) loadinfo->textalloc = (uintptr_t)
@@ -643,6 +678,11 @@ int modlib_load_with_addrenv(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->gotindex >= 0) if (loadinfo->gotindex >= 0)
{ {
binfo("GOT section found! index %d\n", loadinfo->gotindex); 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 */ /* Determine total size to allocate */
+6 -2
View File
@@ -132,11 +132,15 @@ int modlib_uninit(FAR struct module_s *modp)
modp->sectalloc = NULL; modp->sectalloc = NULL;
modp->nsect = 0; modp->nsect = 0;
#else #else
if (modp->xipbase == 0)
{
# if defined(CONFIG_ARCH_USE_TEXT_HEAP) # if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)modp->textalloc); up_textheap_free((FAR void *)modp->textalloc);
# else # else
lib_free((FAR void *)modp->textalloc); lib_free((FAR void *)modp->textalloc);
# endif # endif
}
# if defined(CONFIG_ARCH_USE_DATA_HEAP) # if defined(CONFIG_ARCH_USE_DATA_HEAP)
up_dataheap_free((FAR void *)modp->dataalloc); up_dataheap_free((FAR void *)modp->dataalloc);
# else # else
+1 -1
View File
@@ -99,7 +99,7 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
lib_free(loadinfo->sectalloc); lib_free(loadinfo->sectalloc);
#else #else
if (loadinfo->textalloc != 0) if (loadinfo->textalloc != 0 && loadinfo->xipbase == 0)
{ {
# if defined(CONFIG_ARCH_USE_TEXT_HEAP) # if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)loadinfo->textalloc); up_textheap_free((FAR void *)loadinfo->textalloc);