diff options
author | Chris Johns <chrisj@rtems.org> | 2014-10-26 18:09:41 -0700 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2014-10-31 11:04:15 +1100 |
commit | ae5fe7e6bca2874c5f1ef077204bb63124fb3db3 (patch) | |
tree | 90a6e9e7b414ed3713011267b1fee404b5f6093f /cpukit/libdl/dlfcn.c | |
parent | Added missing stm32f4xxxx_adc.h (diff) | |
download | rtems-ae5fe7e6bca2874c5f1ef077204bb63124fb3db3.tar.bz2 |
cpukit: Add libdl with the Runtime Loader (RTL) code.
This is a merge of the RTL project.
Diffstat (limited to 'cpukit/libdl/dlfcn.c')
-rw-r--r-- | cpukit/libdl/dlfcn.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/cpukit/libdl/dlfcn.c b/cpukit/libdl/dlfcn.c new file mode 100644 index 0000000000..7c102022b2 --- /dev/null +++ b/cpukit/libdl/dlfcn.c @@ -0,0 +1,153 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ +/** + * @file + * + * @ingroup rtl + * + * @brief RTEMS POSIX Dynamic Module Loading Interface. + * + * This is the POSIX interface to run-time loading of code into RTEMS. + */ + +#include <stdint.h> +#include <dlfcn.h> +#include <rtems/rtl/rtl.h> + +static rtems_rtl_obj_t* +dl_get_obj_from_handle (void* handle) +{ + rtems_rtl_obj_t* obj; + + /* + * Handle the special cases provided in NetBSD and Sun documentation. + * http://download.oracle.com/docs/cd/E19253-01/816-5168/dlsym-3c/index.html + * We currently do not manage the loading dependences in the module mappings + * so we cannot handle the searching based on loading order where overriding + * can occur. + */ + + if ((handle == RTLD_DEFAULT) || (handle == RTLD_SELF)) + obj = rtems_rtl_baseimage (); + else + obj = rtems_rtl_check_handle (handle); + + return obj; +} + +void* +dlopen (const char* name, int mode) +{ + rtems_rtl_obj_t* obj = NULL; + + if (!rtems_rtl_lock ()) + return NULL; + + _rtld_debug.r_state = RT_ADD; + _rtld_debug_state (); + + if (name) + obj = rtems_rtl_load_object (name, mode); + else + obj = rtems_rtl_baseimage (); + + _rtld_debug.r_state = RT_CONSISTENT; + _rtld_debug_state(); + + rtems_rtl_unlock (); + + return obj; +} + +int +dlclose (void* handle) +{ + rtems_rtl_obj_t* obj; + int r; + + if (!rtems_rtl_lock ()) + return -1; + + obj = rtems_rtl_check_handle (handle); + if (!obj) + { + rtems_rtl_unlock (); + return -1; + } + + _rtld_debug.r_state = RT_DELETE; + _rtld_debug_state (); + + r = rtems_rtl_unload_object (obj) ? 0 : -1; + + _rtld_debug.r_state = RT_CONSISTENT; + _rtld_debug_state (); + + rtems_rtl_unlock (); + + return r; +} + +void* +dlsym (void* handle, const char *symbol) +{ + rtems_rtl_obj_t* obj; + rtems_rtl_obj_sym_t* sym; + void* symval = NULL; + + if (!rtems_rtl_lock ()) + return NULL; + + obj = dl_get_obj_from_handle (handle); + if (obj) + { + sym = rtems_rtl_symbol_obj_find (obj, symbol); + if (sym) + symval = sym->value; + } + + rtems_rtl_unlock (); + + return symval; +} + +const char* +dlerror (void) +{ + static char msg[64]; + rtems_rtl_get_error (msg, sizeof (msg)); + return msg; +} + +int +dlinfo (void* handle, int request, void* p) +{ + rtems_rtl_obj_t* obj; + int rc = -1; + + if (!rtems_rtl_lock () || !p) + return -1; + + obj = dl_get_obj_from_handle (handle); + if (obj) + { + switch (request) + { + case RTLD_DI_UNRESOLVED: + *((int*) p) = rtems_rtl_obj_unresolved (obj) ? 1 : 0; + rc = 0; + break; + default: + break; + } + } + + rtems_rtl_unlock (); + + return rc; +} |