mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 09:38:37 +08:00
modlib/dlfcn:unify same code
Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
@@ -162,29 +162,30 @@ int unload_module(FAR struct binary_s *binp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||||
for (i = 0; binp->sectalloc[i] != NULL && i < binp->nsect; i++)
|
for (i = 0; binp->sectalloc[i] != NULL && i < binp->nsect; i++)
|
||||||
{
|
|
||||||
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
|
||||||
if (up_textheap_heapmember(binp->sectalloc[i]))
|
|
||||||
{
|
{
|
||||||
up_textheap_free(binp->sectalloc[i]);
|
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
||||||
continue;
|
if (up_textheap_heapmember(binp->sectalloc[i]))
|
||||||
}
|
{
|
||||||
|
up_textheap_free(binp->sectalloc[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
||||||
if (up_dataheap_heapmember(binp->sectalloc[i]))
|
if (up_dataheap_heapmember(binp->sectalloc[i]))
|
||||||
{
|
{
|
||||||
up_dataheap_free(binp->sectalloc[i]);
|
up_dataheap_free(binp->sectalloc[i]);
|
||||||
continue;
|
}
|
||||||
}
|
else
|
||||||
# endif
|
# endif
|
||||||
|
{
|
||||||
|
kumm_free(binp->sectalloc[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kumm_free(binp->sectalloc[i]);
|
binp->alloc[0] = NULL;
|
||||||
}
|
binp->alloc[1] = NULL;
|
||||||
|
|
||||||
binp->alloc[0] = NULL;
|
|
||||||
binp->alloc[1] = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Free allocated address spaces */
|
/* Free allocated address spaces */
|
||||||
|
|||||||
@@ -270,15 +270,6 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
|||||||
{
|
{
|
||||||
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
|
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
|
||||||
|
|
||||||
/* SHF_ALLOC indicates that the section requires memory during
|
|
||||||
* execution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((shdr->sh_flags & SHF_ALLOC) == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||||
if (loadinfo->ehdr.e_type == ET_REL)
|
if (loadinfo->ehdr.e_type == ET_REL)
|
||||||
{
|
{
|
||||||
|
|||||||
+103
-1
@@ -196,7 +196,7 @@ struct mod_loadinfo_s
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||||
uintptr_t *sectalloc; /* All sections memory allocated when ELF file was loaded */
|
FAR uintptr_t *sectalloc; /* All sections memory allocated when ELF file was loaded */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uintptr_t textalloc; /* .text memory allocated when module was loaded */
|
uintptr_t textalloc; /* .text memory allocated when module was loaded */
|
||||||
@@ -563,4 +563,106 @@ int modlib_registry_foreach(mod_callback_t callback, FAR void *arg);
|
|||||||
|
|
||||||
void modlib_freesymtab(FAR struct module_s *modp);
|
void modlib_freesymtab(FAR struct module_s *modp);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_insert
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Verify that the file is an ELF module binary and, if so, load the
|
||||||
|
* module into kernel memory and initialize it for use.
|
||||||
|
*
|
||||||
|
* NOTE: modlib_setsymtab() had to have been called in board-specific OS
|
||||||
|
* logic prior to calling this function from application logic (perhaps via
|
||||||
|
* boardctl(BOARDIOC_OS_SYMTAB). Otherwise, insmod will be unable to
|
||||||
|
* resolve symbols in the OS module.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
*
|
||||||
|
* filename - Full path to the module binary to be loaded
|
||||||
|
* modname - The name that can be used to refer to the module after
|
||||||
|
* it has been loaded.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* A non-NULL module handle that can be used on subsequent calls to other
|
||||||
|
* module interfaces is returned on success. If modlib_insert() was
|
||||||
|
* unable to load the module modlib_insert() will return a NULL handle
|
||||||
|
* and the errno variable will be set appropriately.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR void *modlib_insert(FAR const char *filename, FAR const char *modname);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_getsymbol
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* modlib_getsymbol() returns the address of a symbol defined within the
|
||||||
|
* object that was previously made accessible through a modlib_getsymbol()
|
||||||
|
* call. handle is the value returned from a call to modlib_insert() (and
|
||||||
|
* which has not since been released via a call to modlib_remove()),
|
||||||
|
* name is the symbol's name as a character string.
|
||||||
|
*
|
||||||
|
* The returned symbol address will remain valid until modlib_remove() is
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* handle - The opaque, non-NULL value returned by a previous successful
|
||||||
|
* call to modlib_insert().
|
||||||
|
* name - A pointer to the symbol name string.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address associated with the symbol is returned on success.
|
||||||
|
* If handle does not refer to a valid module opened by modlib_insert(),
|
||||||
|
* or if the named modlib_symbol cannot be found within any of the objects
|
||||||
|
* associated with handle, modlib_getsymbol() will return NULL and the
|
||||||
|
* errno variable will be set appropriately.
|
||||||
|
*
|
||||||
|
* NOTE: This means that the address zero can never be a valid return
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR const void *modlib_getsymbol(FAR void *handle, FAR const char *name);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_remove
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Remove a previously installed module from memory.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* handle - The module handler previously returned by modlib_insert().
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) on success. On any failure, -1 (ERROR) is returned the
|
||||||
|
* errno value is set appropriately.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int modlib_remove(FAR void *handle);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_modhandle
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* modlib_modhandle() returns the module handle for the installed
|
||||||
|
* module with the provided name. A secondary use of this function is to
|
||||||
|
* determine if a module has been loaded or not.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* name - A pointer to the module name string.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The non-NULL module handle previously returned by modlib_insert() is
|
||||||
|
* returned on success. If no module with that name is installed,
|
||||||
|
* modlib_modhandle() will return a NULL handle and the errno variable
|
||||||
|
* will be set appropriately.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_MODLIB_NAMES
|
||||||
|
FAR void *modlib_gethandle(FAR const char *name);
|
||||||
|
#else
|
||||||
|
# define modlib_gethandle(n) NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __INCLUDE_NUTTX_LIB_MODLIB_H */
|
#endif /* __INCLUDE_NUTTX_LIB_MODLIB_H */
|
||||||
|
|||||||
@@ -25,211 +25,13 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <nuttx/module.h>
|
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
#include "libc.h"
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dlremove
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Remove a previously installed shared library from memory.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* handle - The shared library handle previously returned by dlopen().
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* Zero (OK) on success. On any failure, -1 (ERROR) is returned the
|
|
||||||
* errno value is set appropriately.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
|
||||||
static inline int dlremove(FAR void *handle)
|
|
||||||
{
|
|
||||||
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
|
||||||
void (**array)(void);
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
DEBUGASSERT(modp != NULL);
|
|
||||||
|
|
||||||
/* Get exclusive access to the module registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
|
|
||||||
/* Verify that the module is in the registry */
|
|
||||||
|
|
||||||
ret = modlib_registry_verify(modp);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Failed to verify module: %d\n", ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_MODLIB_MAXDEPEND > 0
|
|
||||||
/* Refuse to remove any module that other modules may depend upon. */
|
|
||||||
|
|
||||||
if (modp->dependents > 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Module has dependents: %d\n", modp->dependents);
|
|
||||||
ret = -EBUSY;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Is there an uninitializer? */
|
|
||||||
|
|
||||||
if (modp->modinfo.uninitializer != NULL)
|
|
||||||
{
|
|
||||||
/* Try to uninitialize the module */
|
|
||||||
|
|
||||||
ret = modp->modinfo.uninitializer(modp->modinfo.arg);
|
|
||||||
|
|
||||||
/* Did the module successfully uninitialize? */
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Failed to uninitialize the module: %d\n", ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nullify so that the uninitializer cannot be called again */
|
|
||||||
|
|
||||||
modp->modinfo.uninitializer = NULL;
|
|
||||||
|
|
||||||
/* Call any .fini_array entries in reverse order */
|
|
||||||
|
|
||||||
array = (void (**)(void))modp->finiarr;
|
|
||||||
for (i = (modp->nfini - 1); i >= 0; i--)
|
|
||||||
{
|
|
||||||
array[i]();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->initializer = NULL;
|
|
||||||
modp->modinfo.arg = NULL;
|
|
||||||
modp->modinfo.exports = NULL;
|
|
||||||
modp->modinfo.nexports = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release resources held by the module */
|
|
||||||
|
|
||||||
/* Dynamic shared objects have text and data allocated in one
|
|
||||||
* operation to keep the relative positions between the two
|
|
||||||
* areas relative otherwise references to the GOT will fail
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!modp->dynamic)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < modp->nsect && modp->sectalloc[i] != NULL; i++)
|
|
||||||
{
|
|
||||||
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
|
||||||
if (up_textheap_heapmember(modp->sectalloc[i]))
|
|
||||||
{
|
|
||||||
up_textheap_free(modp->sectalloc[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
|
||||||
if (up_dataheap_heapmember(modp->sectalloc[i]))
|
|
||||||
{
|
|
||||||
up_dataheap_free(modp->sectalloc[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
lib_free(modp->sectalloc[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
lib_free(modp->sectalloc);
|
|
||||||
modp->sectalloc = NULL;
|
|
||||||
modp->nsect = 0;
|
|
||||||
#else
|
|
||||||
if (modp->textalloc != NULL)
|
|
||||||
{
|
|
||||||
/* Free the module memory */
|
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
|
||||||
up_textheap_free((FAR void *)modp->textalloc);
|
|
||||||
#else
|
|
||||||
lib_free((FAR void *)modp->textalloc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modp->dataalloc != NULL)
|
|
||||||
{
|
|
||||||
/* Free the module memory */
|
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
|
|
||||||
up_dataheap_free((FAR void *)modp->dataalloc);
|
|
||||||
#else
|
|
||||||
lib_free((FAR void *)modp->dataalloc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lib_free((FAR void *)modp->textalloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nullify so that the memory cannot be freed again */
|
|
||||||
|
|
||||||
modp->textalloc = NULL;
|
|
||||||
modp->dataalloc = NULL;
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->textsize = 0;
|
|
||||||
modp->datasize = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Free the modules exported symmbols table */
|
|
||||||
|
|
||||||
modlib_freesymtab(modp);
|
|
||||||
|
|
||||||
/* Remove the module from the registry */
|
|
||||||
|
|
||||||
ret = modlib_registry_del(modp);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Failed to remove the module from the registry: %d\n",
|
|
||||||
ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_MODLIB_MAXDEPEND > 0
|
|
||||||
/* Eliminate any dependencies that this module has on other modules */
|
|
||||||
|
|
||||||
modlib_undepend(modp);
|
|
||||||
#endif
|
|
||||||
modlib_registry_unlock();
|
|
||||||
|
|
||||||
/* And free the registry entry */
|
|
||||||
|
|
||||||
lib_free(modp);
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
errout_with_lock:
|
|
||||||
modlib_registry_unlock();
|
|
||||||
set_errno(-ret);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -277,15 +79,11 @@ errout_with_lock:
|
|||||||
|
|
||||||
int dlclose(FAR void *handle)
|
int dlclose(FAR void *handle)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_BUILD_FLAT)
|
#if defined(CONFIG_BUILD_FLAT) || defined(CONFIG_BUILD_PROTECTED)
|
||||||
/* In the FLAT build, a shared library is essentially the same as a kernel
|
/* In the FLAT build, a shared library is essentially the same as a kernel
|
||||||
* module.
|
* module.
|
||||||
*/
|
*
|
||||||
|
* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
|
||||||
return rmmod(handle);
|
|
||||||
|
|
||||||
#elif defined(CONFIG_BUILD_PROTECTED)
|
|
||||||
/* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
|
|
||||||
* must be two copies of the module logic: One residing in kernel
|
* must be two copies of the module logic: One residing in kernel
|
||||||
* space and using the kernel symbol table and one residing in user space
|
* space and using the kernel symbol table and one residing in user space
|
||||||
* using the user space symbol table.
|
* using the user space symbol table.
|
||||||
@@ -293,7 +91,7 @@ int dlclose(FAR void *handle)
|
|||||||
* dlremove() is essentially a clone of rmmod().
|
* dlremove() is essentially a clone of rmmod().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return dlremove(handle);
|
return modlib_remove(handle);
|
||||||
|
|
||||||
#else /* if defined(CONFIG_BUILD_KERNEL) */
|
#else /* if defined(CONFIG_BUILD_KERNEL) */
|
||||||
/* The KERNEL build is considerably more complex: In order to be shared,
|
/* The KERNEL build is considerably more complex: In order to be shared,
|
||||||
|
|||||||
+10
-256
@@ -24,129 +24,17 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <nuttx/envpath.h>
|
#include <nuttx/envpath.h>
|
||||||
#include <nuttx/module.h>
|
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
#include <nuttx/lib/lib.h>
|
||||||
#include "libc.h"
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dldump_loadinfo
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
|
||||||
# if defined(CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_BINFMT)
|
|
||||||
static void dldump_loadinfo(FAR struct mod_loadinfo_s *loadinfo)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
binfo("LOAD_INFO:\n");
|
|
||||||
binfo(" textalloc: %08lx\n", (long)loadinfo->textalloc);
|
|
||||||
binfo(" datastart: %08lx\n", (long)loadinfo->datastart);
|
|
||||||
binfo(" textsize: %ld\n", (long)loadinfo->textsize);
|
|
||||||
binfo(" datasize: %ld\n", (long)loadinfo->datasize);
|
|
||||||
binfo(" filelen: %ld\n", (long)loadinfo->filelen);
|
|
||||||
binfo(" filfd: %d\n", loadinfo->filfd);
|
|
||||||
binfo(" symtabidx: %d\n", loadinfo->symtabidx);
|
|
||||||
binfo(" strtabidx: %d\n", loadinfo->strtabidx);
|
|
||||||
|
|
||||||
binfo("ELF Header:\n");
|
|
||||||
binfo(" e_ident: %02x %02x %02x %02x\n",
|
|
||||||
loadinfo->ehdr.e_ident[0], loadinfo->ehdr.e_ident[1],
|
|
||||||
loadinfo->ehdr.e_ident[2], loadinfo->ehdr.e_ident[3]);
|
|
||||||
binfo(" e_type: %04x\n", loadinfo->ehdr.e_type);
|
|
||||||
binfo(" e_machine: %04x\n", loadinfo->ehdr.e_machine);
|
|
||||||
binfo(" e_version: %08x\n", loadinfo->ehdr.e_version);
|
|
||||||
binfo(" e_entry: %08lx\n", (long)loadinfo->ehdr.e_entry);
|
|
||||||
binfo(" e_phoff: %d\n", loadinfo->ehdr.e_phoff);
|
|
||||||
binfo(" e_shoff: %d\n", loadinfo->ehdr.e_shoff);
|
|
||||||
binfo(" e_flags: %08x\n" , loadinfo->ehdr.e_flags);
|
|
||||||
binfo(" e_ehsize: %d\n", loadinfo->ehdr.e_ehsize);
|
|
||||||
binfo(" e_phentsize: %d\n", loadinfo->ehdr.e_phentsize);
|
|
||||||
binfo(" e_phnum: %d\n", loadinfo->ehdr.e_phnum);
|
|
||||||
binfo(" e_shentsize: %d\n", loadinfo->ehdr.e_shentsize);
|
|
||||||
binfo(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
|
|
||||||
binfo(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
|
|
||||||
|
|
||||||
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
|
|
||||||
{
|
|
||||||
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
|
||||||
{
|
|
||||||
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
|
|
||||||
binfo("Sections %d:\n", i);
|
|
||||||
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
|
||||||
if (loadinfo->ehdr.e_type == ET_REL)
|
|
||||||
{
|
|
||||||
binfo(" sh_alloc: %08jx\n",
|
|
||||||
(uintmax_t)loadinfo->sectalloc[i]);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
binfo(" sh_name: %08x\n", shdr->sh_name);
|
|
||||||
binfo(" sh_type: %08x\n", shdr->sh_type);
|
|
||||||
binfo(" sh_flags: %08x\n", shdr->sh_flags);
|
|
||||||
binfo(" sh_addr: %08x\n", shdr->sh_addr);
|
|
||||||
binfo(" sh_offset: %d\n", shdr->sh_offset);
|
|
||||||
binfo(" sh_size: %d\n", shdr->sh_size);
|
|
||||||
binfo(" sh_link: %d\n", shdr->sh_link);
|
|
||||||
binfo(" sh_info: %d\n", shdr->sh_info);
|
|
||||||
binfo(" sh_addralign: %d\n", shdr->sh_addralign);
|
|
||||||
binfo(" sh_entsize: %d\n", shdr->sh_entsize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadinfo->phdr && loadinfo->ehdr.e_phnum > 0)
|
|
||||||
{
|
|
||||||
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
|
|
||||||
{
|
|
||||||
FAR Elf32_Phdr *phdr = &loadinfo->phdr[i];
|
|
||||||
binfo("Program Header %d:\n", i);
|
|
||||||
binfo(" p_type: %08x\n", phdr->p_type);
|
|
||||||
binfo(" p_offset: %08x\n", phdr->p_offset);
|
|
||||||
binfo(" p_vaddr: %08x\n", phdr->p_vaddr);
|
|
||||||
binfo(" p_paddr: %08x\n", phdr->p_paddr);
|
|
||||||
binfo(" p_filesz: %08x\n", phdr->p_filesz);
|
|
||||||
binfo(" p_memsz: %08x\n", phdr->p_memsz);
|
|
||||||
binfo(" p_flags: %08x\n", phdr->p_flags);
|
|
||||||
binfo(" p_align: %08x\n", phdr->p_align);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
# define dldump_loadinfo(i)
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dldump_initializer
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MODLIB_DUMPBUFFER)
|
|
||||||
static void dldump_initializer(mod_initializer_t initializer,
|
|
||||||
FAR struct mod_loadinfo_s *loadinfo)
|
|
||||||
{
|
|
||||||
modlib_dumpbuffer("Initializer code", (FAR const uint8_t *)initializer,
|
|
||||||
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define dldump_initializer(b,l)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -173,148 +61,7 @@ static void dldump_initializer(mod_initializer_t initializer,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#if defined(CONFIG_BUILD_FLAT) || defined(CONFIG_BUILD_PROTECTED)
|
||||||
/* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
|
|
||||||
* must be two copies of the module logic: One residing in kernel
|
|
||||||
* space and using the kernel symbol table and one residing in user space
|
|
||||||
* using the user space symbol table.
|
|
||||||
*
|
|
||||||
* dlinsert() is essentially a clone of insmod().
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline FAR void *dlinsert(FAR const char *filename)
|
|
||||||
{
|
|
||||||
struct mod_loadinfo_s loadinfo;
|
|
||||||
FAR struct module_s *modp;
|
|
||||||
mod_initializer_t initializer;
|
|
||||||
void (**array)(void);
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
binfo("Loading file: %s\n", filename);
|
|
||||||
|
|
||||||
/* Get exclusive access to the module registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
|
|
||||||
/* Initialize the ELF library to load the program binary. */
|
|
||||||
|
|
||||||
ret = modlib_initialize(filename, &loadinfo);
|
|
||||||
dldump_loadinfo(&loadinfo);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Failed to initialize to load module: %d\n", ret);
|
|
||||||
goto errout_with_loadinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate a module registry entry to hold the module data */
|
|
||||||
|
|
||||||
modp = (FAR struct module_s *)lib_zalloc(sizeof(struct module_s));
|
|
||||||
if (modp == NULL)
|
|
||||||
{
|
|
||||||
ret = -ENOMEM;
|
|
||||||
binfo("Failed to initialize for load of ELF program: %d\n", ret);
|
|
||||||
goto errout_with_loadinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the program binary */
|
|
||||||
|
|
||||||
ret = modlib_load(&loadinfo);
|
|
||||||
dldump_loadinfo(&loadinfo);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
binfo("Failed to load ELF program binary: %d\n", ret);
|
|
||||||
goto errout_with_registry_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bind the program to the kernel symbol table */
|
|
||||||
|
|
||||||
ret = modlib_bind(modp, &loadinfo);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
binfo("Failed to bind symbols program binary: %d\n", ret);
|
|
||||||
goto errout_with_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the load information */
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
|
||||||
modp->sectalloc = (FAR void *)loadinfo.sectalloc;
|
|
||||||
modp->nsect = loadinfo.ehdr.e_shnum;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
modp->textalloc = (FAR void *)loadinfo.textalloc;
|
|
||||||
modp->dataalloc = (FAR void *)loadinfo.datastart;
|
|
||||||
modp->dynamic = (loadinfo.ehdr.e_type == ET_DYN);
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->textsize = loadinfo.textsize;
|
|
||||||
modp->datasize = loadinfo.datasize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get the module initializer entry point */
|
|
||||||
|
|
||||||
initializer = (mod_initializer_t)(loadinfo.textalloc +
|
|
||||||
loadinfo.ehdr.e_entry);
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->initializer = initializer;
|
|
||||||
#endif
|
|
||||||
dldump_initializer(initializer, &loadinfo);
|
|
||||||
|
|
||||||
/* Call the module initializer */
|
|
||||||
|
|
||||||
switch (loadinfo.ehdr.e_type)
|
|
||||||
{
|
|
||||||
case ET_REL :
|
|
||||||
ret = initializer(&modp->modinfo);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
binfo("Failed to initialize the module: %d\n", ret);
|
|
||||||
goto errout_with_load;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ET_DYN :
|
|
||||||
|
|
||||||
/* Process any preinit_array entries */
|
|
||||||
|
|
||||||
array = (void (**)(void)) loadinfo.preiarr;
|
|
||||||
for (i = 0; i < loadinfo.nprei; i++)
|
|
||||||
{
|
|
||||||
array[i]();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process any init_array entries */
|
|
||||||
|
|
||||||
array = (void (**)(void)) loadinfo.initarr;
|
|
||||||
for (i = 0; i < loadinfo.ninit; i++)
|
|
||||||
{
|
|
||||||
array[i]();
|
|
||||||
}
|
|
||||||
|
|
||||||
modp->finiarr = loadinfo.finiarr;
|
|
||||||
modp->nfini = loadinfo.nfini;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the new module entry to the registry */
|
|
||||||
|
|
||||||
modlib_registry_add(modp);
|
|
||||||
|
|
||||||
modlib_uninitialize(&loadinfo);
|
|
||||||
modlib_registry_unlock();
|
|
||||||
return modp;
|
|
||||||
|
|
||||||
errout_with_load:
|
|
||||||
modlib_unload(&loadinfo);
|
|
||||||
modlib_undepend(modp);
|
|
||||||
errout_with_registry_entry:
|
|
||||||
lib_free(modp);
|
|
||||||
errout_with_loadinfo:
|
|
||||||
modlib_uninitialize(&loadinfo);
|
|
||||||
modlib_registry_unlock();
|
|
||||||
set_errno(-ret);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#elif defined(CONFIG_BUILD_FLAT)
|
|
||||||
/* In the FLAT build, a shared library is essentially the same as a kernel
|
/* In the FLAT build, a shared library is essentially the same as a kernel
|
||||||
* module.
|
* module.
|
||||||
*
|
*
|
||||||
@@ -322,6 +69,13 @@ errout_with_loadinfo:
|
|||||||
* - No automatic binding of symbols
|
* - No automatic binding of symbols
|
||||||
* - No dependencies
|
* - No dependencies
|
||||||
* - mode is ignored.
|
* - mode is ignored.
|
||||||
|
*
|
||||||
|
* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
|
||||||
|
* must be two copies of the module logic: One residing in kernel
|
||||||
|
* space and using the kernel symbol table and one residing in user space
|
||||||
|
* using the user space symbol table.
|
||||||
|
*
|
||||||
|
* dlinsert() is essentially a clone of insmod().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline FAR void *dlinsert(FAR const char *filename)
|
static inline FAR void *dlinsert(FAR const char *filename)
|
||||||
@@ -341,7 +95,7 @@ static inline FAR void *dlinsert(FAR const char *filename)
|
|||||||
* name.
|
* name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
handle = insmod(filename, basename(name));
|
handle = modlib_insert(filename, basename(name));
|
||||||
lib_free(name);
|
lib_free(name);
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,87 +25,13 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <nuttx/symtab.h>
|
|
||||||
#include <nuttx/module.h>
|
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: dlgetsym
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* dlgetsym() implements dlsym() for the PROTECTED build.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* handle - The opaque, non-NULL value returned by a previous successful
|
|
||||||
* call to insmod().
|
|
||||||
* name - A pointer to the symbol name string.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* See dlsym().
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
|
||||||
static inline FAR const void *dlgetsym(FAR void *handle,
|
|
||||||
FAR const char *name)
|
|
||||||
{
|
|
||||||
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
|
||||||
FAR const struct symtab_s *symbol;
|
|
||||||
int err;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Verify that the module is in the registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
ret = modlib_registry_verify(modp);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Failed to verify module: %d\n", ret);
|
|
||||||
err = -ret;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does the module have a symbol table? */
|
|
||||||
|
|
||||||
if (modp->modinfo.exports == NULL || modp->modinfo.nexports == 0)
|
|
||||||
{
|
|
||||||
serr("ERROR: Module has no symbol table\n");
|
|
||||||
err = ENOENT;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search the symbol table for the matching symbol */
|
|
||||||
|
|
||||||
symbol = symtab_findbyname(modp->modinfo.exports, name,
|
|
||||||
modp->modinfo.nexports);
|
|
||||||
if (symbol == NULL)
|
|
||||||
{
|
|
||||||
serr("ERROR: Failed to find symbol in symbol \"%s\" in table\n", name);
|
|
||||||
err = ENOENT;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the address within the module associated with the symbol */
|
|
||||||
|
|
||||||
modlib_registry_unlock();
|
|
||||||
DEBUGASSERT(symbol->sym_value != NULL);
|
|
||||||
return symbol->sym_value;
|
|
||||||
|
|
||||||
errout_with_lock:
|
|
||||||
modlib_registry_unlock();
|
|
||||||
set_errno(err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -143,15 +69,11 @@ errout_with_lock:
|
|||||||
|
|
||||||
FAR void *dlsym(FAR void *handle, FAR const char *name)
|
FAR void *dlsym(FAR void *handle, FAR const char *name)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_BUILD_FLAT)
|
#if defined(CONFIG_BUILD_FLAT) || defined(CONFIG_BUILD_PROTECTED)
|
||||||
/* In the FLAT build, a shared library is essentially the same as a kernel
|
/* In the FLAT build, a shared library is essentially the same as a kernel
|
||||||
* module.
|
* module.
|
||||||
*/
|
*
|
||||||
|
* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
|
||||||
return (FAR void *)modsym(handle, name);
|
|
||||||
|
|
||||||
#elif defined(CONFIG_BUILD_PROTECTED)
|
|
||||||
/* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
|
|
||||||
* must be two copies of the module logic: One residing in kernel
|
* must be two copies of the module logic: One residing in kernel
|
||||||
* space and using the kernel symbol table and one residing in user space
|
* space and using the kernel symbol table and one residing in user space
|
||||||
* using the user space symbol table.
|
* using the user space symbol table.
|
||||||
@@ -159,7 +81,7 @@ FAR void *dlsym(FAR void *handle, FAR const char *name)
|
|||||||
* dlgetsem() is essentially a clone of modsym().
|
* dlgetsem() is essentially a clone of modsym().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return (FAR void *)dlgetsym(handle, name);
|
return (FAR void *)modlib_getsymbol(handle, name);
|
||||||
|
|
||||||
#else /* if defined(CONFIG_BUILD_KERNEL) */
|
#else /* if defined(CONFIG_BUILD_KERNEL) */
|
||||||
/* The KERNEL build is considerably more complex: In order to be shared,
|
/* The KERNEL build is considerably more complex: In order to be shared,
|
||||||
|
|||||||
@@ -36,7 +36,11 @@ if(CONFIG_LIBC_MODLIB)
|
|||||||
modlib_symtab.c
|
modlib_symtab.c
|
||||||
modlib_uninit.c
|
modlib_uninit.c
|
||||||
modlib_unload.c
|
modlib_unload.c
|
||||||
modlib_verify.c)
|
modlib_verify.c
|
||||||
|
modlib_gethandle.c
|
||||||
|
modlib_getsymbol.c
|
||||||
|
modlib_insert.c
|
||||||
|
modlib_remove.c)
|
||||||
|
|
||||||
list(APPEND SRCS modlib_globals.S)
|
list(APPEND SRCS modlib_globals.S)
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ CSRCS += modlib_bind.c modlib_depend.c modlib_init.c modlib_iobuffer.c
|
|||||||
CSRCS += modlib_load.c modlib_loadhdrs.c modlib_verify.c
|
CSRCS += modlib_load.c modlib_loadhdrs.c modlib_verify.c
|
||||||
CSRCS += modlib_read.c modlib_registry.c modlib_sections.c
|
CSRCS += modlib_read.c modlib_registry.c modlib_sections.c
|
||||||
CSRCS += modlib_symbols.c modlib_symtab.c modlib_uninit.c modlib_unload.c
|
CSRCS += modlib_symbols.c modlib_symtab.c modlib_uninit.c modlib_unload.c
|
||||||
|
CSRCS += modlib_gethandle.c modlib_getsymbol.c modlib_insert.c
|
||||||
|
CSRCS += modlib_remove.c
|
||||||
|
|
||||||
# Add the modlib directory to the build
|
# Add the modlib directory to the build
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* libs/libc/modlib/modlib_gethandle.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_modhandle
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* modlib_modhandle() returns the module handle for the installed
|
||||||
|
* module with the provided name. A secondary use of this function is to
|
||||||
|
* determine if a module has been loaded or not.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* name - A pointer to the module name string.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The non-NULL module handle previously returned by modlib_insert() is
|
||||||
|
* returned on success. If no module with that name is installed,
|
||||||
|
* modlib_modhandle() will return a NULL handle and the errno variable
|
||||||
|
* will be set appropriately.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_MODLIB_NAMES
|
||||||
|
|
||||||
|
FAR void *modlib_gethandle(FAR const char *name)
|
||||||
|
{
|
||||||
|
FAR struct module_s *modp;
|
||||||
|
|
||||||
|
DEBUGASSERT(name != NULL);
|
||||||
|
|
||||||
|
/* Get exclusive access to the module registry */
|
||||||
|
|
||||||
|
modlib_registry_lock();
|
||||||
|
|
||||||
|
/* Find the module entry for this name in the registry */
|
||||||
|
|
||||||
|
modp = modlib_registry_find(name);
|
||||||
|
if (modp == NULL)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to find module %s\n", name);
|
||||||
|
set_errno(ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
modlib_registry_unlock();
|
||||||
|
return modp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_MODLIB_NAMES */
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* libs/libc/modlib/modlib_getsymbol.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/lib/modlib.h>
|
||||||
|
#include <nuttx/symtab.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_getsymbol
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* modlib_getsymbol() returns the address of a symbol defined within the
|
||||||
|
* object that was previously made accessible through a modlib_getsymbol()
|
||||||
|
* call. handle is the value returned from a call to modlib_insert() (and
|
||||||
|
* which has not since been released via a call to modlib_remove()),
|
||||||
|
* name is the symbol's name as a character string.
|
||||||
|
*
|
||||||
|
* The returned symbol address will remain valid until modlib_remove() is
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* handle - The opaque, non-NULL value returned by a previous successful
|
||||||
|
* call to modlib_insert().
|
||||||
|
* name - A pointer to the symbol name string.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address associated with the symbol is returned on success.
|
||||||
|
* If handle does not refer to a valid module opened by modlib_insert(),
|
||||||
|
* or if the named modlib_symbol cannot be found within any of the objects
|
||||||
|
* associated with handle, modlib_getsymbol() will return NULL and the
|
||||||
|
* errno variable will be set appropriately.
|
||||||
|
*
|
||||||
|
* NOTE: This means that the address zero can never be a valid return
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR const void *modlib_getsymbol(FAR void *handle, FAR const char *name)
|
||||||
|
{
|
||||||
|
FAR struct module_s *modp = handle;
|
||||||
|
FAR const struct symtab_s *symbol;
|
||||||
|
int err;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Verify that the module is in the registry */
|
||||||
|
|
||||||
|
modlib_registry_lock();
|
||||||
|
ret = modlib_registry_verify(modp);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to verify module: %d\n", ret);
|
||||||
|
err = -ret;
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does the module have a symbol table? */
|
||||||
|
|
||||||
|
if (modp->modinfo.exports == NULL || modp->modinfo.nexports == 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Module has no symbol table\n");
|
||||||
|
err = ENOENT;
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search the symbol table for the matching symbol */
|
||||||
|
|
||||||
|
symbol = symtab_findbyname(modp->modinfo.exports, name,
|
||||||
|
modp->modinfo.nexports);
|
||||||
|
|
||||||
|
modlib_registry_unlock();
|
||||||
|
if (symbol == NULL)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to find symbol in symbol \"%s\" in table\n", name);
|
||||||
|
set_errno(ENOENT);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the address within the module associated with the symbol */
|
||||||
|
|
||||||
|
DEBUGASSERT(symbol->sym_value != NULL);
|
||||||
|
return symbol->sym_value;
|
||||||
|
|
||||||
|
errout_with_lock:
|
||||||
|
modlib_registry_unlock();
|
||||||
|
set_errno(err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* libs/libc/modlib/modlib_insert.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <nuttx/lib/lib.h>
|
||||||
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_dumploadinfo
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_BINFMT_INFO
|
||||||
|
static void modlib_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
binfo("LOAD_INFO:\n");
|
||||||
|
binfo(" textalloc: %08lx\n", (long)loadinfo->textalloc);
|
||||||
|
binfo(" datastart: %08lx\n", (long)loadinfo->datastart);
|
||||||
|
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);
|
||||||
|
binfo(" filfd: %d\n", loadinfo->filfd);
|
||||||
|
binfo(" symtabidx: %d\n", loadinfo->symtabidx);
|
||||||
|
binfo(" strtabidx: %d\n", loadinfo->strtabidx);
|
||||||
|
|
||||||
|
binfo("ELF Header:\n");
|
||||||
|
binfo(" e_ident: %02x %02x %02x %02x\n",
|
||||||
|
loadinfo->ehdr.e_ident[0], loadinfo->ehdr.e_ident[1],
|
||||||
|
loadinfo->ehdr.e_ident[2], loadinfo->ehdr.e_ident[3]);
|
||||||
|
binfo(" e_type: %04x\n", loadinfo->ehdr.e_type);
|
||||||
|
binfo(" e_machine: %04x\n", loadinfo->ehdr.e_machine);
|
||||||
|
binfo(" e_version: %08x\n", loadinfo->ehdr.e_version);
|
||||||
|
binfo(" e_entry: %08lx\n", (long)loadinfo->ehdr.e_entry);
|
||||||
|
binfo(" e_phoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_phoff);
|
||||||
|
binfo(" e_shoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_shoff);
|
||||||
|
binfo(" e_flags: %08x\n", loadinfo->ehdr.e_flags);
|
||||||
|
binfo(" e_ehsize: %d\n", loadinfo->ehdr.e_ehsize);
|
||||||
|
binfo(" e_phentsize: %d\n", loadinfo->ehdr.e_phentsize);
|
||||||
|
binfo(" e_phnum: %d\n", loadinfo->ehdr.e_phnum);
|
||||||
|
binfo(" e_shentsize: %d\n", loadinfo->ehdr.e_shentsize);
|
||||||
|
binfo(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
|
||||||
|
binfo(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
|
||||||
|
|
||||||
|
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
||||||
|
{
|
||||||
|
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
|
||||||
|
binfo("Sections %d:\n", i);
|
||||||
|
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||||
|
if (loadinfo->ehdr.e_type == ET_REL)
|
||||||
|
{
|
||||||
|
binfo(" sh_alloc: %08jx\n",
|
||||||
|
(uintmax_t)loadinfo->sectalloc[i]);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
binfo(" sh_name: %08x\n", shdr->sh_name);
|
||||||
|
binfo(" sh_type: %08x\n", shdr->sh_type);
|
||||||
|
binfo(" sh_flags: %08jx\n", (uintmax_t)shdr->sh_flags);
|
||||||
|
binfo(" sh_addr: %08jx\n", (uintmax_t)shdr->sh_addr);
|
||||||
|
binfo(" sh_offset: %ju\n", (uintmax_t)shdr->sh_offset);
|
||||||
|
binfo(" sh_size: %ju\n", (uintmax_t)shdr->sh_size);
|
||||||
|
binfo(" sh_link: %d\n", shdr->sh_link);
|
||||||
|
binfo(" sh_info: %d\n", shdr->sh_info);
|
||||||
|
binfo(" sh_addralign: %ju\n", (uintmax_t)shdr->sh_addralign);
|
||||||
|
binfo(" sh_entsize: %ju\n", (uintmax_t)shdr->sh_entsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define modlib_dumploadinfo(i)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_dumpinitializer
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_MODLIB_DUMPBUFFER
|
||||||
|
static void modlib_dumpinitializer(mod_initializer_t initializer,
|
||||||
|
FAR struct mod_loadinfo_s *loadinfo)
|
||||||
|
{
|
||||||
|
modlib_dumpbuffer("Initializer code", (FAR const uint8_t *)initializer,
|
||||||
|
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define modlib_dumpinitializer(b,l)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_insert
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Verify that the file is an ELF module binary and, if so, load the
|
||||||
|
* module into kernel memory and initialize it for use.
|
||||||
|
*
|
||||||
|
* NOTE: modlib_setsymtab() had to have been called in board-specific OS
|
||||||
|
* logic prior to calling this function from application logic (perhaps via
|
||||||
|
* boardctl(BOARDIOC_OS_SYMTAB). Otherwise, insmod will be unable to
|
||||||
|
* resolve symbols in the OS module.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
*
|
||||||
|
* filename - Full path to the module binary to be loaded
|
||||||
|
* modname - The name that can be used to refer to the module after
|
||||||
|
* it has been loaded.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* A non-NULL module handle that can be used on subsequent calls to other
|
||||||
|
* module interfaces is returned on success. If modlib_insert() was
|
||||||
|
* unable to load the module modlib_insert() will return a NULL handle
|
||||||
|
* and the errno variable will be set appropriately.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR void *modlib_insert(FAR const char *filename, FAR const char *modname)
|
||||||
|
{
|
||||||
|
struct mod_loadinfo_s loadinfo;
|
||||||
|
FAR struct module_s *modp;
|
||||||
|
mod_initializer_t initializer;
|
||||||
|
FAR void (**array)(void);
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
DEBUGASSERT(filename != NULL && modname != NULL);
|
||||||
|
binfo("Loading file: %s\n", filename);
|
||||||
|
|
||||||
|
/* Get exclusive access to the module registry */
|
||||||
|
|
||||||
|
modlib_registry_lock();
|
||||||
|
|
||||||
|
/* Check if this module is already installed */
|
||||||
|
|
||||||
|
#ifdef HAVE_MODLIB_NAMES
|
||||||
|
if (modlib_registry_find(modname) != NULL)
|
||||||
|
{
|
||||||
|
modlib_registry_unlock();
|
||||||
|
set_errno(EEXIST);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialize the ELF library to load the program binary. */
|
||||||
|
|
||||||
|
ret = modlib_initialize(filename, &loadinfo);
|
||||||
|
modlib_dumploadinfo(&loadinfo);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to initialize to load module: %d\n", ret);
|
||||||
|
goto errout_with_loadinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a module registry entry to hold the module data */
|
||||||
|
|
||||||
|
modp = lib_zalloc(sizeof(struct module_s));
|
||||||
|
if (modp == NULL)
|
||||||
|
{
|
||||||
|
berr("Failed to allocate struct module_s\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto errout_with_loadinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_MODLIB_NAMES
|
||||||
|
/* Save the module name in the registry entry */
|
||||||
|
|
||||||
|
strlcpy(modp->modname, modname, sizeof(modp->modname));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Load the program binary */
|
||||||
|
|
||||||
|
ret = modlib_load(&loadinfo);
|
||||||
|
modlib_dumploadinfo(&loadinfo);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
binfo("Failed to load ELF program binary: %d\n", ret);
|
||||||
|
goto errout_with_registry_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bind the program to the kernel symbol table */
|
||||||
|
|
||||||
|
ret = modlib_bind(modp, &loadinfo);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
binfo("Failed to bind symbols program binary: %d\n", ret);
|
||||||
|
goto errout_with_load;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the load information */
|
||||||
|
|
||||||
|
modp->textalloc = (FAR void *)loadinfo.textalloc;
|
||||||
|
modp->dataalloc = (FAR void *)loadinfo.datastart;
|
||||||
|
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||||
|
modp->textsize = loadinfo.textsize;
|
||||||
|
modp->datasize = loadinfo.datasize;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get the module initializer entry point */
|
||||||
|
|
||||||
|
initializer = (mod_initializer_t)(loadinfo.textalloc +
|
||||||
|
loadinfo.ehdr.e_entry);
|
||||||
|
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||||
|
modp->initializer = initializer;
|
||||||
|
#endif
|
||||||
|
modlib_dumpinitializer(initializer, &loadinfo);
|
||||||
|
|
||||||
|
/* Call the module initializer */
|
||||||
|
|
||||||
|
switch (loadinfo.ehdr.e_type)
|
||||||
|
{
|
||||||
|
case ET_REL :
|
||||||
|
ret = initializer(&modp->modinfo);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
binfo("Failed to initialize the module: %d\n", ret);
|
||||||
|
goto errout_with_load;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ET_DYN :
|
||||||
|
|
||||||
|
/* Process any preinit_array entries */
|
||||||
|
|
||||||
|
array = (FAR void (**)(void))loadinfo.preiarr;
|
||||||
|
for (i = 0; i < loadinfo.nprei; i++)
|
||||||
|
{
|
||||||
|
array[i]();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process any init_array entries */
|
||||||
|
|
||||||
|
array = (FAR void (**)(void))loadinfo.initarr;
|
||||||
|
for (i = 0; i < loadinfo.ninit; i++)
|
||||||
|
{
|
||||||
|
array[i]();
|
||||||
|
}
|
||||||
|
|
||||||
|
modp->finiarr = loadinfo.finiarr;
|
||||||
|
modp->nfini = loadinfo.nfini;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the new module entry to the registry */
|
||||||
|
|
||||||
|
modlib_registry_add(modp);
|
||||||
|
|
||||||
|
modlib_uninitialize(&loadinfo);
|
||||||
|
modlib_registry_unlock();
|
||||||
|
return modp;
|
||||||
|
|
||||||
|
errout_with_load:
|
||||||
|
modlib_unload(&loadinfo);
|
||||||
|
#if CONFIG_MODLIB_MAXDEPEND > 0
|
||||||
|
modlib_undepend(modp);
|
||||||
|
#endif
|
||||||
|
errout_with_registry_entry:
|
||||||
|
lib_free(modp);
|
||||||
|
errout_with_loadinfo:
|
||||||
|
modlib_uninitialize(&loadinfo);
|
||||||
|
modlib_registry_unlock();
|
||||||
|
set_errno(-ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
|
|||||||
/* Allocate memory info for all sections */
|
/* Allocate memory info for all sections */
|
||||||
|
|
||||||
loadinfo->sectalloc = lib_zalloc(sizeof(uintptr_t) *
|
loadinfo->sectalloc = lib_zalloc(sizeof(uintptr_t) *
|
||||||
loadinfo->ehdr.e_shnum);
|
loadinfo->ehdr.e_shnum);
|
||||||
if (loadinfo->sectalloc == NULL)
|
if (loadinfo->sectalloc == NULL)
|
||||||
{
|
{
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* libs/libc/modlib/modlib_remove.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
#include <nuttx/lib/lib.h>
|
||||||
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: modlib_remove
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Remove a previously installed module from memory.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* handle - The module handler previously returned by modlib_insert().
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) on success. On any failure, -1 (ERROR) is returned the
|
||||||
|
* errno value is set appropriately.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int modlib_remove(FAR void *handle)
|
||||||
|
{
|
||||||
|
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(modp != NULL);
|
||||||
|
|
||||||
|
/* Get exclusive access to the module registry */
|
||||||
|
|
||||||
|
modlib_registry_lock();
|
||||||
|
|
||||||
|
/* Verify that the module is in the registry */
|
||||||
|
|
||||||
|
ret = modlib_registry_verify(modp);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to verify module: %d\n", ret);
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MODLIB_MAXDEPEND > 0
|
||||||
|
/* Refuse to remove any module that other modules may depend upon. */
|
||||||
|
|
||||||
|
if (modp->dependents > 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Module has dependents: %d\n", modp->dependents);
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Is there an uninitializer? */
|
||||||
|
|
||||||
|
if (modp->modinfo.uninitializer != NULL)
|
||||||
|
{
|
||||||
|
/* Try to uninitialize the module */
|
||||||
|
|
||||||
|
ret = modp->modinfo.uninitializer(modp->modinfo.arg);
|
||||||
|
|
||||||
|
/* Did the module successfully uninitialize? */
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to uninitialize the module: %d\n", ret);
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nullify so that the uninitializer cannot be called again */
|
||||||
|
|
||||||
|
modp->modinfo.uninitializer = NULL;
|
||||||
|
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||||
|
modp->initializer = NULL;
|
||||||
|
modp->modinfo.arg = NULL;
|
||||||
|
modp->modinfo.exports = NULL;
|
||||||
|
modp->modinfo.nexports = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release resources held by the module */
|
||||||
|
|
||||||
|
if (modp->textalloc != NULL || modp->dataalloc != NULL)
|
||||||
|
{
|
||||||
|
/* Free the module memory and nullify so that the memory cannot
|
||||||
|
* be freed again
|
||||||
|
*
|
||||||
|
* NOTE: For dynamic shared objects there is only a single
|
||||||
|
* allocation: the text/data were allocated in one operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!modp->dynamic)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < modp->nsect && modp->sectalloc[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
||||||
|
if (up_textheap_heapmember(modp->sectalloc[i]))
|
||||||
|
{
|
||||||
|
up_textheap_free(modp->sectalloc[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
||||||
|
if (up_dataheap_heapmember(modp->sectalloc[i]))
|
||||||
|
{
|
||||||
|
up_dataheap_free(modp->sectalloc[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
lib_free(modp->sectalloc[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
lib_free(modp->sectalloc);
|
||||||
|
modp->sectalloc = NULL;
|
||||||
|
modp->nsect = 0;
|
||||||
|
#else
|
||||||
|
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||||
|
up_textheap_free((FAR void *)modp->textalloc);
|
||||||
|
# else
|
||||||
|
lib_free((FAR void *)modp->textalloc);
|
||||||
|
# endif
|
||||||
|
# if defined(CONFIG_ARCH_USE_DATA_HEAP)
|
||||||
|
up_dataheap_free((FAR void *)modp->dataalloc);
|
||||||
|
# else
|
||||||
|
lib_free((FAR void *)modp->dataalloc);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lib_free((FAR void *)modp->textalloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
modp->textalloc = NULL;
|
||||||
|
modp->dataalloc = NULL;
|
||||||
|
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||||
|
modp->textsize = 0;
|
||||||
|
modp->datasize = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the module from the registry */
|
||||||
|
|
||||||
|
ret = modlib_registry_del(modp);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
berr("ERROR: Failed to remove the module from the registry: %d\n",
|
||||||
|
ret);
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MODLIB_MAXDEPEND > 0
|
||||||
|
/* Eliminate any dependencies that this module has on other modules */
|
||||||
|
|
||||||
|
modlib_undepend(modp);
|
||||||
|
#endif
|
||||||
|
modlib_registry_unlock();
|
||||||
|
|
||||||
|
/* And free the registry entry */
|
||||||
|
|
||||||
|
lib_free(modp);
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
errout_with_lock:
|
||||||
|
modlib_registry_unlock();
|
||||||
|
set_errno(-ret);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
@@ -72,39 +72,40 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
|
|||||||
if (up_textheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
|
if (up_textheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
|
||||||
{
|
{
|
||||||
up_textheap_free((FAR void *)loadinfo->sectalloc[i]);
|
up_textheap_free((FAR void *)loadinfo->sectalloc[i]);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
||||||
if (up_dataheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
|
if (up_dataheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
|
||||||
{
|
{
|
||||||
up_dataheap_free((FAR void *)loadinfo->sectalloc[i]);
|
up_dataheap_free((FAR void *)loadinfo->sectalloc[i]);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
# endif
|
# endif
|
||||||
|
{
|
||||||
lib_free((FAR void *)loadinfo->sectalloc[i]);
|
lib_free((FAR void *)loadinfo->sectalloc[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_free(loadinfo->sectalloc);
|
lib_free(loadinfo->sectalloc);
|
||||||
#else
|
#else
|
||||||
if (loadinfo->textalloc != 0)
|
if (loadinfo->textalloc != 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);
|
||||||
#else
|
# else
|
||||||
lib_free((FAR void *)loadinfo->textalloc);
|
lib_free((FAR void *)loadinfo->textalloc);
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadinfo->datastart != 0)
|
if (loadinfo->datastart != 0)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
|
# if defined(CONFIG_ARCH_USE_DATA_HEAP)
|
||||||
up_dataheap_free((FAR void *)loadinfo->datastart);
|
up_dataheap_free((FAR void *)loadinfo->datastart);
|
||||||
#else
|
# else
|
||||||
lib_free((FAR void *)loadinfo->datastart);
|
lib_free((FAR void *)loadinfo->datastart);
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-240
@@ -26,110 +26,11 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <nuttx/arch.h>
|
|
||||||
#include <nuttx/kmalloc.h>
|
|
||||||
#include <nuttx/module.h>
|
#include <nuttx/module.h>
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
#ifdef CONFIG_MODULE
|
#ifdef CONFIG_MODULE
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: mod_dumploadinfo
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_BINFMT_INFO
|
|
||||||
static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
binfo("LOAD_INFO:\n");
|
|
||||||
binfo(" textalloc: %08lx\n", (long)loadinfo->textalloc);
|
|
||||||
binfo(" datastart: %08lx\n", (long)loadinfo->datastart);
|
|
||||||
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);
|
|
||||||
binfo(" filfd: %d\n", loadinfo->filfd);
|
|
||||||
binfo(" symtabidx: %d\n", loadinfo->symtabidx);
|
|
||||||
binfo(" strtabidx: %d\n", loadinfo->strtabidx);
|
|
||||||
|
|
||||||
binfo("ELF Header:\n");
|
|
||||||
binfo(" e_ident: %02x %02x %02x %02x\n",
|
|
||||||
loadinfo->ehdr.e_ident[0], loadinfo->ehdr.e_ident[1],
|
|
||||||
loadinfo->ehdr.e_ident[2], loadinfo->ehdr.e_ident[3]);
|
|
||||||
binfo(" e_type: %04x\n", loadinfo->ehdr.e_type);
|
|
||||||
binfo(" e_machine: %04x\n", loadinfo->ehdr.e_machine);
|
|
||||||
binfo(" e_version: %08x\n", loadinfo->ehdr.e_version);
|
|
||||||
binfo(" e_entry: %08lx\n", (long)loadinfo->ehdr.e_entry);
|
|
||||||
binfo(" e_phoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_phoff);
|
|
||||||
binfo(" e_shoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_shoff);
|
|
||||||
binfo(" e_flags: %08x\n", loadinfo->ehdr.e_flags);
|
|
||||||
binfo(" e_ehsize: %d\n", loadinfo->ehdr.e_ehsize);
|
|
||||||
binfo(" e_phentsize: %d\n", loadinfo->ehdr.e_phentsize);
|
|
||||||
binfo(" e_phnum: %d\n", loadinfo->ehdr.e_phnum);
|
|
||||||
binfo(" e_shentsize: %d\n", loadinfo->ehdr.e_shentsize);
|
|
||||||
binfo(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
|
|
||||||
binfo(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
|
|
||||||
|
|
||||||
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
|
|
||||||
{
|
|
||||||
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
|
||||||
{
|
|
||||||
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
|
|
||||||
binfo("Sections %d:\n", i);
|
|
||||||
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
|
||||||
if (loadinfo->ehdr.e_type == ET_REL)
|
|
||||||
{
|
|
||||||
binfo(" sh_alloc: %08jx\n",
|
|
||||||
(uintmax_t)loadinfo->sectalloc[i]);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
binfo(" sh_name: %08x\n", shdr->sh_name);
|
|
||||||
binfo(" sh_type: %08x\n", shdr->sh_type);
|
|
||||||
binfo(" sh_flags: %08jx\n", (uintmax_t)shdr->sh_flags);
|
|
||||||
binfo(" sh_addr: %08jx\n", (uintmax_t)shdr->sh_addr);
|
|
||||||
binfo(" sh_offset: %ju\n", (uintmax_t)shdr->sh_offset);
|
|
||||||
binfo(" sh_size: %ju\n", (uintmax_t)shdr->sh_size);
|
|
||||||
binfo(" sh_link: %d\n", shdr->sh_link);
|
|
||||||
binfo(" sh_info: %d\n", shdr->sh_info);
|
|
||||||
binfo(" sh_addralign: %ju\n", (uintmax_t)shdr->sh_addralign);
|
|
||||||
binfo(" sh_entsize: %ju\n", (uintmax_t)shdr->sh_entsize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define mod_dumploadinfo(i)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: mod_dumpinitializer
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_MODLIB_DUMPBUFFER
|
|
||||||
static void mod_dumpinitializer(mod_initializer_t initializer,
|
|
||||||
FAR struct mod_loadinfo_s *loadinfo)
|
|
||||||
{
|
|
||||||
modlib_dumpbuffer("Initializer code", (FAR const uint8_t *)initializer,
|
|
||||||
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define mod_dumpinitializer(b,l)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -162,147 +63,7 @@ static void mod_dumpinitializer(mod_initializer_t initializer,
|
|||||||
|
|
||||||
FAR void *insmod(FAR const char *filename, FAR const char *modname)
|
FAR void *insmod(FAR const char *filename, FAR const char *modname)
|
||||||
{
|
{
|
||||||
struct mod_loadinfo_s loadinfo;
|
return modlib_insert(filename, modname);
|
||||||
FAR struct module_s *modp;
|
|
||||||
mod_initializer_t initializer;
|
|
||||||
FAR void (**array)(void);
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
DEBUGASSERT(filename != NULL && modname != NULL);
|
|
||||||
binfo("Loading file: %s\n", filename);
|
|
||||||
|
|
||||||
/* Get exclusive access to the module registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
|
|
||||||
/* Check if this module is already installed */
|
|
||||||
|
|
||||||
if (modlib_registry_find(modname) != NULL)
|
|
||||||
{
|
|
||||||
ret = -EEXIST;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the ELF library to load the program binary. */
|
|
||||||
|
|
||||||
ret = modlib_initialize(filename, &loadinfo);
|
|
||||||
mod_dumploadinfo(&loadinfo);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to initialize to load module: %d\n", ret);
|
|
||||||
goto errout_with_loadinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate a module registry entry to hold the module data */
|
|
||||||
|
|
||||||
modp = kmm_zalloc(sizeof(struct module_s));
|
|
||||||
if (modp == NULL)
|
|
||||||
{
|
|
||||||
berr("Failed to allocate struct module_s\n");
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto errout_with_loadinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_MODLIB_NAMES
|
|
||||||
/* Save the module name in the registry entry */
|
|
||||||
|
|
||||||
strlcpy(modp->modname, modname, sizeof(modp->modname));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Load the program binary */
|
|
||||||
|
|
||||||
ret = modlib_load(&loadinfo);
|
|
||||||
mod_dumploadinfo(&loadinfo);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
binfo("Failed to load ELF program binary: %d\n", ret);
|
|
||||||
goto errout_with_registry_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bind the program to the kernel symbol table */
|
|
||||||
|
|
||||||
ret = modlib_bind(modp, &loadinfo);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
binfo("Failed to bind symbols program binary: %d\n", ret);
|
|
||||||
goto errout_with_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the load information */
|
|
||||||
|
|
||||||
modp->textalloc = (FAR void *)loadinfo.textalloc;
|
|
||||||
modp->dataalloc = (FAR void *)loadinfo.datastart;
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->textsize = loadinfo.textsize;
|
|
||||||
modp->datasize = loadinfo.datasize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get the module initializer entry point */
|
|
||||||
|
|
||||||
initializer = (mod_initializer_t)(loadinfo.textalloc +
|
|
||||||
loadinfo.ehdr.e_entry);
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->initializer = initializer;
|
|
||||||
#endif
|
|
||||||
mod_dumpinitializer(initializer, &loadinfo);
|
|
||||||
|
|
||||||
/* Call the module initializer */
|
|
||||||
|
|
||||||
switch (loadinfo.ehdr.e_type)
|
|
||||||
{
|
|
||||||
case ET_REL :
|
|
||||||
ret = initializer(&modp->modinfo);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
binfo("Failed to initialize the module: %d\n", ret);
|
|
||||||
goto errout_with_load;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ET_DYN :
|
|
||||||
|
|
||||||
/* Process any preinit_array entries */
|
|
||||||
|
|
||||||
array = (FAR void (**)(void))loadinfo.preiarr;
|
|
||||||
for (i = 0; i < loadinfo.nprei; i++)
|
|
||||||
{
|
|
||||||
array[i]();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process any init_array entries */
|
|
||||||
|
|
||||||
array = (FAR void (**)(void))loadinfo.initarr;
|
|
||||||
for (i = 0; i < loadinfo.ninit; i++)
|
|
||||||
{
|
|
||||||
array[i]();
|
|
||||||
}
|
|
||||||
|
|
||||||
modp->finiarr = loadinfo.finiarr;
|
|
||||||
modp->nfini = loadinfo.nfini;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the new module entry to the registry */
|
|
||||||
|
|
||||||
modlib_registry_add(modp);
|
|
||||||
|
|
||||||
modlib_uninitialize(&loadinfo);
|
|
||||||
modlib_registry_unlock();
|
|
||||||
return modp;
|
|
||||||
|
|
||||||
errout_with_load:
|
|
||||||
modlib_unload(&loadinfo);
|
|
||||||
#if CONFIG_MODLIB_MAXDEPEND > 0
|
|
||||||
modlib_undepend(modp);
|
|
||||||
#endif
|
|
||||||
errout_with_registry_entry:
|
|
||||||
kmm_free(modp);
|
|
||||||
errout_with_loadinfo:
|
|
||||||
modlib_uninitialize(&loadinfo);
|
|
||||||
errout_with_lock:
|
|
||||||
modlib_registry_unlock();
|
|
||||||
set_errno(-ret);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_MODULE */
|
#endif /* CONFIG_MODULE */
|
||||||
|
|||||||
@@ -26,11 +26,6 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <nuttx/module.h>
|
#include <nuttx/module.h>
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
@@ -60,25 +55,7 @@
|
|||||||
|
|
||||||
FAR void *modhandle(FAR const char *name)
|
FAR void *modhandle(FAR const char *name)
|
||||||
{
|
{
|
||||||
FAR struct module_s *modp;
|
return modlib_gethandle(name);
|
||||||
|
|
||||||
DEBUGASSERT(name != NULL);
|
|
||||||
|
|
||||||
/* Get exclusive access to the module registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
|
|
||||||
/* Find the module entry for this name in the registry */
|
|
||||||
|
|
||||||
modp = modlib_registry_find(name);
|
|
||||||
if (modp == NULL)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to find module %s\n", name);
|
|
||||||
set_errno(ENOENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
modlib_registry_unlock();
|
|
||||||
return modp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_MODULE */
|
#endif /* CONFIG_MODULE */
|
||||||
|
|||||||
@@ -26,11 +26,6 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <nuttx/symtab.h>
|
|
||||||
#include <nuttx/module.h>
|
#include <nuttx/module.h>
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
@@ -69,50 +64,5 @@
|
|||||||
|
|
||||||
FAR const void *modsym(FAR void *handle, FAR const char *name)
|
FAR const void *modsym(FAR void *handle, FAR const char *name)
|
||||||
{
|
{
|
||||||
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
return modlib_getsymbol(handle, name);
|
||||||
FAR const struct symtab_s *symbol;
|
|
||||||
int err;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Verify that the module is in the registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
ret = modlib_registry_verify(modp);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to verify module: %d\n", ret);
|
|
||||||
err = -ret;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does the module have a symbol table? */
|
|
||||||
|
|
||||||
if (modp->modinfo.exports == NULL || modp->modinfo.nexports == 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Module has no symbol table\n");
|
|
||||||
err = ENOENT;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search the symbol table for the matching symbol */
|
|
||||||
|
|
||||||
symbol = symtab_findbyname(modp->modinfo.exports, name,
|
|
||||||
modp->modinfo.nexports);
|
|
||||||
if (symbol == NULL)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to find symbol in symbol \"%s\" in table\n", name);
|
|
||||||
err = ENOENT;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the address within the module associated with the symbol */
|
|
||||||
|
|
||||||
modlib_registry_unlock();
|
|
||||||
DEBUGASSERT(symbol->sym_value != NULL);
|
|
||||||
return symbol->sym_value;
|
|
||||||
|
|
||||||
errout_with_lock:
|
|
||||||
modlib_registry_unlock();
|
|
||||||
set_errno(err);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-154
@@ -26,12 +26,6 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <nuttx/kmalloc.h>
|
|
||||||
#include <nuttx/module.h>
|
#include <nuttx/module.h>
|
||||||
#include <nuttx/lib/modlib.h>
|
#include <nuttx/lib/modlib.h>
|
||||||
|
|
||||||
@@ -58,154 +52,7 @@
|
|||||||
|
|
||||||
int rmmod(FAR void *handle)
|
int rmmod(FAR void *handle)
|
||||||
{
|
{
|
||||||
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
return modlib_remove(handle);
|
||||||
int ret;
|
|
||||||
|
|
||||||
DEBUGASSERT(modp != NULL);
|
|
||||||
|
|
||||||
/* Get exclusive access to the module registry */
|
|
||||||
|
|
||||||
modlib_registry_lock();
|
|
||||||
|
|
||||||
/* Verify that the module is in the registry */
|
|
||||||
|
|
||||||
ret = modlib_registry_verify(modp);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to verify module: %d\n", ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_MODLIB_MAXDEPEND > 0
|
|
||||||
/* Refuse to remove any module that other modules may depend upon. */
|
|
||||||
|
|
||||||
if (modp->dependents > 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Module has dependents: %d\n", modp->dependents);
|
|
||||||
ret = -EBUSY;
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Is there an uninitializer? */
|
|
||||||
|
|
||||||
if (modp->modinfo.uninitializer != NULL)
|
|
||||||
{
|
|
||||||
/* Try to uninitialize the module */
|
|
||||||
|
|
||||||
ret = modp->modinfo.uninitializer(modp->modinfo.arg);
|
|
||||||
|
|
||||||
/* Did the module successfully uninitialize? */
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to uninitialize the module: %d\n", ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nullify so that the uninitializer cannot be called again */
|
|
||||||
|
|
||||||
modp->modinfo.uninitializer = NULL;
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->initializer = NULL;
|
|
||||||
modp->modinfo.arg = NULL;
|
|
||||||
modp->modinfo.exports = NULL;
|
|
||||||
modp->modinfo.nexports = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release resources held by the module */
|
|
||||||
|
|
||||||
if (modp->textalloc != NULL || modp->dataalloc != NULL)
|
|
||||||
{
|
|
||||||
/* Free the module memory and nullify so that the memory cannot
|
|
||||||
* be freed again
|
|
||||||
*
|
|
||||||
* NOTE: For dynamic shared objects there is only a single
|
|
||||||
* allocation: the text/data were allocated in one operation
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!modp->dynamic)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < modp->nsect && modp->sectalloc[i] != NULL; i++)
|
|
||||||
{
|
|
||||||
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
|
||||||
if (up_textheap_heapmember(modp->sectalloc[i]))
|
|
||||||
{
|
|
||||||
up_textheap_free(modp->sectalloc[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef CONFIG_ARCH_USE_DATA_HEAP
|
|
||||||
if (up_dataheap_heapmember(modp->sectalloc[i]))
|
|
||||||
{
|
|
||||||
up_dataheap_free(modp->sectalloc[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
kmm_free(modp->sectalloc[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
kmm_free(modp->sectalloc);
|
|
||||||
modp->sectalloc = NULL;
|
|
||||||
modp->nsect = 0;
|
|
||||||
#else
|
|
||||||
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
|
||||||
up_textheap_free((FAR void *)modp->textalloc);
|
|
||||||
# else
|
|
||||||
kmm_free((FAR void *)modp->textalloc);
|
|
||||||
# endif
|
|
||||||
# if defined(CONFIG_ARCH_USE_DATA_HEAP)
|
|
||||||
up_dataheap_free((FAR void *)modp->dataalloc);
|
|
||||||
# else
|
|
||||||
kmm_free((FAR void *)modp->dataalloc);
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kmm_free((FAR void *)modp->textalloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
modp->textalloc = NULL;
|
|
||||||
modp->dataalloc = NULL;
|
|
||||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
|
||||||
modp->textsize = 0;
|
|
||||||
modp->datasize = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the module from the registry */
|
|
||||||
|
|
||||||
ret = modlib_registry_del(modp);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
berr("ERROR: Failed to remove the module from the registry: %d\n",
|
|
||||||
ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_MODLIB_MAXDEPEND > 0
|
|
||||||
/* Eliminate any dependencies that this module has on other modules */
|
|
||||||
|
|
||||||
modlib_undepend(modp);
|
|
||||||
#endif
|
|
||||||
modlib_registry_unlock();
|
|
||||||
|
|
||||||
/* And free the registry entry */
|
|
||||||
|
|
||||||
kmm_free(modp);
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
errout_with_lock:
|
|
||||||
modlib_registry_unlock();
|
|
||||||
set_errno(-ret);
|
|
||||||
return ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_MODULE */
|
#endif /* CONFIG_MODULE */
|
||||||
|
|||||||
Reference in New Issue
Block a user