Skip to content

Commit

Permalink
modlib/dlfcn:unify same code
Browse files Browse the repository at this point in the history
Signed-off-by: anjiahao <[email protected]>
  • Loading branch information
anjiahao1 committed Sep 29, 2024
1 parent c5ed623 commit d2a6789
Show file tree
Hide file tree
Showing 18 changed files with 847 additions and 1,039 deletions.
9 changes: 5 additions & 4 deletions binfmt/binfmt_unloadmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,19 +168,20 @@ int unload_module(FAR struct binary_s *binp)
if (up_textheap_heapmember(binp->sectalloc[i]))
{
up_textheap_free(binp->sectalloc[i]);
continue;
}
else
# endif

# ifdef CONFIG_ARCH_USE_DATA_HEAP
if (up_dataheap_heapmember(binp->sectalloc[i]))
{
up_dataheap_free(binp->sectalloc[i]);
continue;
}
else
# endif

kumm_free(binp->sectalloc[i]);
{
kumm_free(binp->sectalloc[i]);
}
}

binp->alloc[0] = NULL;
Expand Down
9 changes: 0 additions & 9 deletions binfmt/libelf/libelf_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,6 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
{
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
if (loadinfo->ehdr.e_type == ET_REL)
{
Expand Down
104 changes: 103 additions & 1 deletion include/nuttx/lib/modlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ struct mod_loadinfo_s
*/

#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

uintptr_t textalloc; /* .text memory allocated when module was loaded */
Expand Down Expand Up @@ -563,4 +563,106 @@ int modlib_registry_foreach(mod_callback_t callback, FAR void *arg);

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 */
210 changes: 4 additions & 206 deletions libs/libc/dlfcn/lib_dlclose.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,211 +25,13 @@
#include <nuttx/config.h>

#include <dlfcn.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>

#include <nuttx/module.h>
#include <nuttx/lib/modlib.h>

#include "libc.h"

/****************************************************************************
* 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
****************************************************************************/
Expand Down Expand Up @@ -277,23 +79,19 @@ static inline int dlremove(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
* module.
*/

return rmmod(handle);

#elif defined(CONFIG_BUILD_PROTECTED)
/* The PROTECTED build is equivalent to the FLAT build EXCEPT that there
*
* 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.
*
* dlremove() is essentially a clone of rmmod().
*/

return dlremove(handle);
return modlib_remove(handle);

#else /* if defined(CONFIG_BUILD_KERNEL) */
/* The KERNEL build is considerably more complex: In order to be shared,
Expand Down
Loading

0 comments on commit d2a6789

Please sign in to comment.