summaryrefslogtreecommitdiff
path: root/components/libc/libdl/dlmodule.c
diff options
context:
space:
mode:
authortonyzheng-rockchip <[email protected]>2019-12-26 11:03:51 +0800
committertonyzheng-rockchip <[email protected]>2019-12-27 14:27:31 +0800
commitd910372010f92c9c0b836a035aaa556dd3818198 (patch)
tree9e84fa3c85802dc0c04a16fba294ba1063441a2e /components/libc/libdl/dlmodule.c
parent20d1c13be61493fca0a1e27bdbd567ea2619b321 (diff)
Fix dlmodule must depends on file system issue
解决dlmodule只能依赖于文件系统的问题; 增加dlmodule扩展接口,以适应更多需求;
Diffstat (limited to 'components/libc/libdl/dlmodule.c')
-rw-r--r--components/libc/libdl/dlmodule.c190
1 files changed, 189 insertions, 1 deletions
diff --git a/components/libc/libdl/dlmodule.c b/components/libc/libdl/dlmodule.c
index dbebfc8961..2829b7df7d 100644
--- a/components/libc/libdl/dlmodule.c
+++ b/components/libc/libdl/dlmodule.c
@@ -14,7 +14,9 @@
#include "dlmodule.h"
#include "dlelf.h"
+#if defined(RT_USING_POSIX)
#include <dfs_posix.h>
+#endif
#define DBG_TAG "DLMD"
#define DBG_LVL DBG_INFO
@@ -419,11 +421,14 @@ struct rt_dlmodule *rt_module_self(void)
struct rt_dlmodule* dlmodule_load(const char* filename)
{
- int fd, length = 0;
+#if defined(RT_USING_POSIX)
+ int fd = -1, length = 0;
+#endif
rt_err_t ret = RT_EOK;
rt_uint8_t *module_ptr = RT_NULL;
struct rt_dlmodule *module = RT_NULL;
+#if defined(RT_USING_POSIX)
fd = open(filename, O_RDONLY, 0);
if (fd >= 0)
{
@@ -446,6 +451,9 @@ struct rt_dlmodule* dlmodule_load(const char* filename)
{
goto __exit;
}
+#endif
+
+ if (!module_ptr) goto __exit;
/* check ELF header */
if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
@@ -512,7 +520,9 @@ struct rt_dlmodule* dlmodule_load(const char* filename)
return module;
__exit:
+#if defined(RT_USING_POSIX)
if (fd >= 0) close(fd);
+#endif
if (module_ptr) rt_free(module_ptr);
if (module) dlmodule_destroy(module);
@@ -558,6 +568,184 @@ struct rt_dlmodule* dlmodule_exec(const char* pgname, const char* cmd, int cmd_s
return module;
}
+#if defined(RT_USING_CUSTOM_DLMODULE)
+struct rt_dlmodule* dlmodule_load_custom(const char* filename, struct rt_dlmodule_ops* ops)
+{
+#if defined(RT_USING_POSIX)
+ int fd = -1, length = 0;
+#endif
+ rt_err_t ret = RT_EOK;
+ rt_uint8_t *module_ptr = RT_NULL;
+ struct rt_dlmodule *module = RT_NULL;
+
+ if (ops)
+ {
+ RT_ASSERT(ops->load);
+ RT_ASSERT(ops->unload);
+ module_ptr = ops->load(filename);
+ }
+#if defined(RT_USING_POSIX)
+ else
+ {
+ fd = open(filename, O_RDONLY, 0);
+ if (fd >= 0)
+ {
+ length = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+
+ if (length == 0) goto __exit;
+
+ module_ptr = (uint8_t*) rt_malloc (length);
+ if (!module_ptr) goto __exit;
+
+ if (read(fd, module_ptr, length) != length)
+ goto __exit;
+
+ /* close file and release fd */
+ close(fd);
+ fd = -1;
+ }
+ else
+ {
+ goto __exit;
+ }
+ }
+#endif
+
+ if (!module_ptr) goto __exit;
+
+ /* check ELF header */
+ if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
+ rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
+ {
+ rt_kprintf("Module: magic error\n");
+ goto __exit;
+ }
+
+ /* check ELF class */
+ if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
+ {
+ rt_kprintf("Module: ELF class error\n");
+ goto __exit;
+ }
+
+ module = dlmodule_create();
+ if (!module) goto __exit;
+
+ /* set the name of module */
+ _dlmodule_set_name(module, filename);
+
+ LOG_D("rt_module_load: %.*s", RT_NAME_MAX, module->parent.name);
+
+ if (elf_module->e_type == ET_REL)
+ {
+ ret = dlmodule_load_relocated_object(module, module_ptr);
+ }
+ else if (elf_module->e_type == ET_DYN)
+ {
+ ret = dlmodule_load_shared_object(module, module_ptr);
+ }
+ else
+ {
+ rt_kprintf("Module: unsupported elf type\n");
+ goto __exit;
+ }
+
+ /* check return value */
+ if (ret != RT_EOK) goto __exit;
+
+ /* release module data */
+ if (ops)
+ {
+ ops->unload(module_ptr);
+ }
+ else
+ {
+ rt_free(module_ptr);
+ }
+
+ /* increase module reference count */
+ module->nref ++;
+
+ /* deal with cache */
+#ifdef RT_USING_CACHE
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, module->mem_space, module->mem_size);
+ rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, module->mem_space, module->mem_size);
+#endif
+
+ /* set module initialization and cleanup function */
+ module->init_func = dlsym(module, "module_init");
+ module->cleanup_func = dlsym(module, "module_cleanup");
+ module->stat = RT_DLMODULE_STAT_INIT;
+ /* do module initialization */
+ if (module->init_func)
+ {
+ module->init_func(module);
+ }
+
+ return module;
+
+__exit:
+#if defined(RT_USING_POSIX)
+ if (fd >= 0) close(fd);
+#endif
+ if (module_ptr)
+ {
+ if (ops)
+ {
+ ops->unload(module_ptr);
+ }
+ else
+ {
+ rt_free(module_ptr);
+ }
+ }
+
+ if (module) dlmodule_destroy(module);
+
+ return RT_NULL;
+}
+
+struct rt_dlmodule* dlmodule_exec_custom(const char* pgname, const char* cmd, int cmd_size, struct rt_dlmodule_ops* ops)
+{
+ struct rt_dlmodule *module = RT_NULL;
+
+ module = dlmodule_load_custom(pgname, ops);
+ if (module)
+ {
+ if (module->entry_addr)
+ {
+ /* exec this module */
+ rt_thread_t tid;
+
+ module->cmd_line = rt_strdup(cmd);
+
+ /* check stack size and priority */
+ if (module->priority > RT_THREAD_PRIORITY_MAX) module->priority = RT_THREAD_PRIORITY_MAX - 1;
+ if (module->stack_size < 2048 || module->stack_size > (1024 * 32)) module->stack_size = 2048;
+
+ tid = rt_thread_create(module->parent.name, _dlmodule_thread_entry, (void*)module,
+ module->stack_size, module->priority, 10);
+ if (tid)
+ {
+ tid->module_id = module;
+ module->main_thread = tid;
+
+ rt_thread_startup(tid);
+ }
+ else
+ {
+ /* destory dl module */
+ dlmodule_destroy(module);
+ module = RT_NULL;
+ }
+ }
+ }
+
+ return module;
+}
+#endif
+
void dlmodule_exit(int ret_code)
{
rt_thread_t thread;