From 121366d6c89e97ac9c1257d08b4af59ee68c4ec3 Mon Sep 17 00:00:00 2001 From: tonyzheng-rockchip Date: Thu, 26 Dec 2019 11:03:51 +0800 Subject: [PATCH 1/2] Fix dlmodule must depends on file system issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解决dlmodule只能依赖于文件系统的问题; 增加dlmodule扩展接口,以适应更多需求; --- components/libc/libdl/dlmodule.c | 184 ++++++++++++++++++++++++++++++- components/libc/libdl/dlmodule.h | 10 ++ 2 files changed, 193 insertions(+), 1 deletion(-) diff --git a/components/libc/libdl/dlmodule.c b/components/libc/libdl/dlmodule.c index dbebfc8961..25e9beaeb0 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 +#endif #define DBG_TAG "DLMD" #define DBG_LVL DBG_INFO @@ -419,11 +421,12 @@ struct rt_dlmodule *rt_module_self(void) struct rt_dlmodule* dlmodule_load(const char* filename) { - int fd, length = 0; + int fd = -1, length = 0; 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 +449,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 +518,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 +566,180 @@ struct rt_dlmodule* dlmodule_exec(const char* pgname, const char* cmd, int cmd_s return module; } +struct rt_dlmodule* dlmodule_ext_load(const char* filename, struct rt_dlmodule_ops* ops) +{ + int fd = -1, length = 0; + 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_ext_exec(const char* pgname, const char* cmd, int cmd_size, struct rt_dlmodule_ops* ops) +{ + struct rt_dlmodule *module = RT_NULL; + + module = dlmodule_ext_load(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; +} + void dlmodule_exit(int ret_code) { rt_thread_t thread; diff --git a/components/libc/libdl/dlmodule.h b/components/libc/libdl/dlmodule.h index 4a4ead3303..48e42e0079 100644 --- a/components/libc/libdl/dlmodule.h +++ b/components/libc/libdl/dlmodule.h @@ -59,6 +59,12 @@ struct rt_dlmodule struct rt_module_symtab *symtab; /* module symbol table */ }; +struct rt_dlmodule_ops +{ + rt_uint8_t *(*load)(const char* filename); /* load dlmodule file data */ + rt_err_t (*unload)(rt_uint8_t *param); /* unload dlmodule file data */ +}; + struct rt_dlmodule *dlmodule_create(void); rt_err_t dlmodule_destroy(struct rt_dlmodule* module); @@ -66,6 +72,10 @@ struct rt_dlmodule *dlmodule_self(void); struct rt_dlmodule *dlmodule_load(const char* pgname); struct rt_dlmodule *dlmodule_exec(const char* pgname, const char* cmd, int cmd_size); + +struct rt_dlmodule* dlmodule_ext_load(const char* filename, struct rt_dlmodule_ops* ops); +struct rt_dlmodule* dlmodule_ext_exec(const char* pgname, const char* cmd, int cmd_size, struct rt_dlmodule_ops* ops); + void dlmodule_exit(int ret_code); struct rt_dlmodule *dlmodule_find(const char *name); From d910372010f92c9c0b836a035aaa556dd3818198 Mon Sep 17 00:00:00 2001 From: tonyzheng-rockchip Date: Thu, 26 Dec 2019 11:03:51 +0800 Subject: [PATCH 2/2] Fix dlmodule must depends on file system issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解决dlmodule只能依赖于文件系统的问题; 增加dlmodule扩展接口,以适应更多需求; --- components/libc/Kconfig | 10 ++ components/libc/libdl/dlmodule.c | 190 ++++++++++++++++++++++++++++++- components/libc/libdl/dlmodule.h | 12 ++ 3 files changed, 211 insertions(+), 1 deletion(-) diff --git a/components/libc/Kconfig b/components/libc/Kconfig index 2d1e9315f1..26e156522b 100644 --- a/components/libc/Kconfig +++ b/components/libc/Kconfig @@ -34,9 +34,19 @@ if RT_USING_LIBC && RT_USING_DFS default n endif +endif + +if RT_USING_LIBC config RT_USING_MODULE bool "Enable dynamic module with dlopen/dlsym/dlclose feature" default n + + if RT_USING_MODULE + config RT_USING_CUSTOM_DLMODULE + bool "Enable load dynamic module by custom" + default n + endif + endif if RT_USING_LIBC != y 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 +#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; diff --git a/components/libc/libdl/dlmodule.h b/components/libc/libdl/dlmodule.h index 4a4ead3303..b366c7603e 100644 --- a/components/libc/libdl/dlmodule.h +++ b/components/libc/libdl/dlmodule.h @@ -59,6 +59,12 @@ struct rt_dlmodule struct rt_module_symtab *symtab; /* module symbol table */ }; +struct rt_dlmodule_ops +{ + rt_uint8_t *(*load)(const char* filename); /* load dlmodule file data */ + rt_err_t (*unload)(rt_uint8_t *param); /* unload dlmodule file data */ +}; + struct rt_dlmodule *dlmodule_create(void); rt_err_t dlmodule_destroy(struct rt_dlmodule* module); @@ -66,6 +72,12 @@ struct rt_dlmodule *dlmodule_self(void); struct rt_dlmodule *dlmodule_load(const char* pgname); struct rt_dlmodule *dlmodule_exec(const char* pgname, const char* cmd, int cmd_size); + +#if defined(RT_USING_CUSTOM_DLMODULE) +struct rt_dlmodule* dlmodule_load_custom(const char* filename, struct rt_dlmodule_ops* ops); +struct rt_dlmodule* dlmodule_exec_custom(const char* pgname, const char* cmd, int cmd_size, struct rt_dlmodule_ops* ops); +#endif + void dlmodule_exit(int ret_code); struct rt_dlmodule *dlmodule_find(const char *name);