mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
modlib:if elf in romfs/tmpfs, try use xipbase
Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
@@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user