浏览代码

Merge pull request #3294 from tonyzheng-rockchip/fix-dlmodule

Fix dlmodule must depends on file system issue
Bernard Xiong 5 年之前
父节点
当前提交
c2322353aa
共有 3 个文件被更改,包括 211 次插入1 次删除
  1. 10 0
      components/libc/Kconfig
  2. 189 1
      components/libc/libdl/dlmodule.c
  3. 12 0
      components/libc/libdl/dlmodule.h

+ 10 - 0
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

+ 189 - 1
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;

+ 12 - 0
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);