libs/libc/dllfcn, sched/init: Add LD_LIBRARY_PATH environment variable support.

This commit is contained in:
anchao 2019-01-26 11:47:14 -06:00 committed by Gregory Nutt
parent 9e2238f6cd
commit 88efb84847
3 changed files with 119 additions and 53 deletions

View File

@ -17,4 +17,16 @@ config LIBC_DLLFCN
A work in progress, hence, marked EXPERIMENTAL
if LIBC_DLLFCN
config LDPATH_INITIAL
string "Initial LD_LIBRARY_PATH Value"
default ""
depends on LIB_ENVPATH
---help---
The initial value of the LD_LIBRARY_PATH variable. This is the
colon-separated list of absolute paths. E.g., "/lib:/usr/lib:/system/lib"
endif
# endmenu # Shared Library Support

View File

@ -46,6 +46,7 @@
#include <assert.h>
#include <errno.h>
#include <nuttx/envpath.h>
#include <nuttx/module.h>
#include <nuttx/lib/modlib.h>
@ -161,6 +162,14 @@ static void dldump_initializer(mod_initializer_t initializer,
****************************************************************************/
#ifdef 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;
@ -257,6 +266,50 @@ errout_with_lock:
set_errno(-ret);
return NULL;
}
#elif defined(CONFIG_BUILD_FLAT)
/* In the FLAT build, a shared library is essentially the same as a kernel
* module.
*
* REVIST: Missing functionality:
* - No automatic binding of symbols
* - No dependencies
* - mode is ignored.
*/
static inline FAR void *dlinsert(FAR const char *filename)
{
FAR void *handle;
FAR char *name;
DEBUGASSERT(filename != NULL);
name = strdup(filename);
if (name == NULL)
{
return NULL;
}
/* Then install the file using the basename of the file as the module name. */
handle = insmod(filename, basename(name));
free(name);
return handle;
}
#else /* if defined(CONFIG_BUILD_KERNEL) */
/* The KERNEL build is considerably more complex: In order to be shared,
* the .text portion of the module must be (1) build for PIC/PID operation
* and (2) must like in a shared memory region accessible from all
* processes. The .data/.bss portion of the module must be allocated in
* the user space of each process, but must lie at the same virtual address
* so that it can be referenced from the one copy of the text in the shared
* memory region.
*/
static inline FAR void *dlinsert(FAR const char *filename)
{
#warning Missing logic
return NULL;
}
#endif
/****************************************************************************
@ -365,61 +418,58 @@ errout_with_lock:
FAR void *dlopen(FAR const char *file, int mode)
{
#if defined(CONFIG_BUILD_FLAT)
FAR void *handle;
FAR char *name;
FAR void *handle = NULL;
DEBUGASSERT(file != NULL);
/* In the FLAT build, a shared library is essentially the same as a kernel
* module.
*
* REVIST: Missing functionality:
* - No automatic binding of symbols
* - No dependencies
* - mode is ignored.
*/
/* Use the basename of the file as the module name.
* REVISIT: This places an non-standard restriction. We cannot install
* two modules of the same name event though they lie in different
* directories.
*/
name = strdup(file);
if (name == NULL)
#ifdef CONFIG_LIB_ENVPATH
if (file[0] != '/')
{
return NULL;
FAR const char *relpath;
FAR char *fullpath;
ENVPATH_HANDLE env;
/* Set aside the relative path */
relpath = file;
/* Initialize to traverse the LD_LIBRARY_PATH variable */
env = envpath_init("LD_LIBRARY_PATH");
if (env)
{
/* Get the next absolute file path */
while ((fullpath = envpath_next(env, relpath)) != NULL)
{
/* Try to load the file at this path */
handle = dlinsert(fullpath);
/* Free the allocated fullpath */
lib_free(fullpath);
/* Break out of the loop with handle != NULL on success */
if (handle != NULL)
{
break;
}
}
/* Release the traversal handle */
envpath_release(env);
}
}
else
#endif
{
/* We already have the one and only absolute path to the file to
* be loaded.
*/
handle = dlinsert(file);
}
/* Then install the file using the basename of the file as the module name. */
handle = insmod(file, basename(name));
free(name);
return 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
* 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().
*/
return dlinsert(file);
#else /* if defined(CONFIG_BUILD_KERNEL) */
/* The KERNEL build is considerably more complex: In order to be shared,
* the .text portion of the module must be (1) build for PIC/PID operation
* and (2) must like in a shared memory region accessible from all
* processes. The .data/.bss portion of the module must be allocated in
* the user space of each process, but must lie at the same virtual address
* so that it can be referenced from the one copy of the text in the shared
* memory region.
*/
#warning Missing logic
return NULL;
#endif
}

View File

@ -436,6 +436,10 @@ int os_bringup(void)
(void)setenv("PATH", CONFIG_PATH_INITIAL, 1);
#endif
#if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_LDPATH_INITIAL)
(void)setenv("LD_LIBRARY_PATH", CONFIG_LDPATH_INITIAL, 1);
#endif
/* Start the page fill worker kernel thread that will resolve page faults.
* This should always be the first thread started because it may have to
* resolve page faults in other threads
@ -458,7 +462,7 @@ int os_bringup(void)
/* We an save a few bytes by discarding the IDLE thread's environment. */
#if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL)
#if !defined(CONFIG_DISABLE_ENVIRON) && (defined(CONFIG_PATH_INITIAL) || defined(CONFIG_LDPATH_INITIAL))
(void)clearenv();
#endif