diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 1d9156ce4b..edb7c0c921 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -584,38 +584,6 @@ FINSH_FUNCTION_EXPORT(list_device, list device in system); MSH_CMD_EXPORT(list_device, list device in system); #endif -#ifdef RT_USING_MODULE -#include - -int list_module(void) -{ - int maxlen; - struct rt_module *module; - struct rt_list_node *list, *node; - struct rt_object_information *info; - const char *item_title = "module"; - - info = rt_object_get_information(RT_Object_Class_Module); - list = &info->object_list; - - maxlen = object_name_maxlen(item_title, list); - - rt_kprintf("%-*.s ref address \n", maxlen, item_title); object_split(maxlen); - rt_kprintf( " -------- ------------\n"); - for (node = list->next; node != list; node = node->next) - { - module = (struct rt_module *)(rt_list_entry(node, struct rt_object, list)); - rt_kprintf("%-*.*s %-04d 0x%08x\n", - maxlen, RT_NAME_MAX, - module->parent.name, module->nref, module->module_space); - } - - return 0; -} -FINSH_FUNCTION_EXPORT(list_module, list module in system); -MSH_CMD_EXPORT(list_module, list module in system); -#endif - long list(void) { #ifndef FINSH_USING_MSH_ONLY diff --git a/components/finsh/msh.c b/components/finsh/msh.c index b036e2c02e..456486c17e 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -37,8 +37,12 @@ #include #endif +#ifdef RT_USING_MODULE +#include +#endif + #ifndef FINSH_ARG_MAX -#define FINSH_ARG_MAX 10 +#define FINSH_ARG_MAX 8 #endif typedef int (*cmd_function_t)(int argc, char **argv); @@ -64,7 +68,6 @@ static int msh_exit(int argc, char **argv) { /* return to finsh shell mode */ __msh_state = RT_FALSE; - return 0; } FINSH_FUNCTION_EXPORT_ALIAS(msh_exit, __cmd_exit, return to RT-Thread shell mode.); @@ -254,7 +257,7 @@ int msh_exec_module(const char *cmd_line, int size) { /* found program */ close(fd); - rt_module_exec_cmd(pg_name, cmd_line, size); + dlmodule_exec(pg_name, cmd_line, size); ret = 0; } else diff --git a/components/libc/Kconfig b/components/libc/Kconfig index 2b4f6af8b0..b2abe69850 100644 --- a/components/libc/Kconfig +++ b/components/libc/Kconfig @@ -28,11 +28,9 @@ if RT_USING_LIBC && RT_USING_DFS default n endif - if RT_USING_MODULE - config RT_USING_LIBDL - bool "Enable dlopen/dlsym/dlclose feature" + config RT_USING_MODULE + bool "Enable dynamic module with dlopen/dlsym/dlclose feature" default n - endif endif endmenu diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index 822182ba93..cc72efe9ea 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/components/libc/compilers/newlib/syscalls.c @@ -11,6 +11,10 @@ #include #endif +#ifdef RT_USING_MODULE +#include +#endif + /* Reentrant versions of system calls. */ int @@ -379,18 +383,12 @@ _free_r (struct _reent *ptr, void *addr) } void -_exit (int status) +exit (int status) { #ifdef RT_USING_MODULE - rt_module_t module; - - module = rt_module_self(); - if (module != RT_NULL) + if (dlmodule_self()) { - rt_thread_suspend(rt_thread_self()); - - /* re-schedule */ - rt_schedule(); + dlmodule_exit(status); } #endif diff --git a/components/libc/libdl/SConscript b/components/libc/libdl/SConscript index 493dd4b256..93636e4b7a 100644 --- a/components/libc/libdl/SConscript +++ b/components/libc/libdl/SConscript @@ -1,14 +1,14 @@ from building import * Import('rtconfig') -src = Glob('*.c') + Glob('*.cpp') +src = Glob('*.c') + Glob('*.cpp') + Glob('arch/*.c') cwd = GetCurrentDir() group = [] CPPPATH = [cwd] if rtconfig.PLATFORM == 'gcc': group = DefineGroup('libc', src, - depend = ['RT_USING_MODULE', 'RT_USING_LIBDL'], + depend = ['RT_USING_MODULE'], CPPPATH = CPPPATH) Return('group') diff --git a/components/libc/libdl/arch/arm.c b/components/libc/libdl/arch/arm.c new file mode 100644 index 0000000000..a53c04f0bc --- /dev/null +++ b/components/libc/libdl/arch/arm.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/08/29 Bernard first version + */ + +#include "../dlmodule.h" +#include "../dlelf.h" + +#ifdef __arm__ +int dlmodule_relocate(struct rt_dlmodule *module, Elf32_Rel *rel, Elf32_Addr sym_val) +{ + Elf32_Addr *where, tmp; + Elf32_Sword addend, offset; + rt_uint32_t upper, lower, sign, j1, j2; + + where = (Elf32_Addr *)((rt_uint8_t *)module->mem_space + + rel->r_offset + - module->vstart_addr); + switch (ELF32_R_TYPE(rel->r_info)) + { + case R_ARM_NONE: + break; + case R_ARM_ABS32: + *where += (Elf32_Addr)sym_val; + RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n", + where, *where)); + break; + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_CALL: + case R_ARM_JUMP24: + addend = *where & 0x00ffffff; + if (addend & 0x00800000) + addend |= 0xff000000; + tmp = sym_val - (Elf32_Addr)where + (addend << 2); + tmp >>= 2; + *where = (*where & 0xff000000) | (tmp & 0x00ffffff); + RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n", + where, *where)); + break; + case R_ARM_REL32: + *where += sym_val - (Elf32_Addr)where; + RT_DEBUG_LOG(RT_DEBUG_MODULE, + ("R_ARM_REL32: %x -> %x, sym %x, offset %x\n", + where, *where, sym_val, rel->r_offset)); + break; + case R_ARM_V4BX: + *where &= 0xf000000f; + *where |= 0x01a0f000; + break; + + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *where = (Elf32_Addr)sym_val; + RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n", + where, *where, sym_val)); + break; +#if 0 /* To do */ + case R_ARM_GOT_BREL: + temp = (Elf32_Addr)sym_val; + *where = (Elf32_Addr)&temp; + RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n", + where, *where, sym_val)); + break; +#endif + + case R_ARM_RELATIVE: + *where = (Elf32_Addr)sym_val + *where; + RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n", + where, *where, sym_val)); + break; + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + upper = *(rt_uint16_t *)where; + lower = *(rt_uint16_t *)((Elf32_Addr)where + 2); + + sign = (upper >> 10) & 1; + j1 = (lower >> 13) & 1; + j2 = (lower >> 11) & 1; + offset = (sign << 24) | + ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((upper & 0x03ff) << 12) | + ((lower & 0x07ff) << 1); + if (offset & 0x01000000) + offset -= 0x02000000; + offset += sym_val - (Elf32_Addr)where; + + if (!(offset & 1) || + offset <= (rt_int32_t)0xff000000 || + offset >= (rt_int32_t)0x01000000) + { + rt_kprintf("Module: Only Thumb addresses allowed\n"); + + return -1; + } + + sign = (offset >> 24) & 1; + j1 = sign ^ (~(offset >> 23) & 1); + j2 = sign ^ (~(offset >> 22) & 1); + *(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) | + (sign << 10) | + ((offset >> 12) & 0x03ff)); + *(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) | + (j1 << 13) | (j2 << 11) | + ((offset >> 1) & 0x07ff)); + upper = *(rt_uint16_t *)where; + lower = *(rt_uint16_t *)((Elf32_Addr)where + 2); + break; + default: + return -1; + } + + return 0; +} +#endif diff --git a/components/libc/libdl/dlclose.c b/components/libc/libdl/dlclose.c index af070891fc..1202e13f2c 100644 --- a/components/libc/libdl/dlclose.c +++ b/components/libc/libdl/dlclose.c @@ -1,36 +1,39 @@ /* - * File : dlclose.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * Copyright (c) 2006-2018, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version + * Date Author Notes + * 2010-11-17 yi.qiu first version */ #include #include -int dlclose (void *handle) +#include "dlmodule.h" + +int dlclose(void *handle) { - rt_module_t module; - - RT_ASSERT(handle != RT_NULL); - - module = (rt_module_t)handle; - module->nref--; - - if(module->nref <= 0) - { - rt_module_unload(module); - } + struct rt_dlmodule *module; - return RT_TRUE; + RT_ASSERT(handle != RT_NULL); + + module = (struct rt_dlmodule *)handle; + + rt_enter_critical(); + module->nref--; + if (module->nref <= 0) + { + rt_exit_critical(); + + dlmodule_destroy(module); + } + else + { + rt_exit_critical(); + } + + return RT_TRUE; } - RTM_EXPORT(dlclose) - diff --git a/components/libc/libdl/dlelf.c b/components/libc/libdl/dlelf.c new file mode 100644 index 0000000000..8075af1374 --- /dev/null +++ b/components/libc/libdl/dlelf.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/08/29 Bernard first version + */ + +#include "dlmodule.h" +#include "dlelf.h" + +#define DBG_SECTION_NAME "DLMD" +#define DBG_ENABLE // enable debug macro +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include // must after of DEBUG_ENABLE or some other options + +rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_ptr) +{ + rt_bool_t linked = RT_FALSE; + rt_uint32_t index, module_size = 0; + Elf32_Addr vstart_addr, vend_addr; + rt_bool_t has_vstart; + + RT_ASSERT(module_ptr != RT_NULL); + + if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0) + { + /* rtmlinker finished */ + linked = RT_TRUE; + } + + /* get the ELF image size */ + has_vstart = RT_FALSE; + vstart_addr = vend_addr = RT_NULL; + for (index = 0; index < elf_module->e_phnum; index++) + { + if (phdr[index].p_type != PT_LOAD) + continue; + + LOG_D("LOAD segment: %d, 0x%p, 0x%08x", index, phdr[index].p_vaddr, phdr[index].p_memsz); + + if (phdr[index].p_memsz < phdr[index].p_filesz) + { + rt_kprintf("invalid elf: segment %d: p_memsz: %d, p_filesz: %d\n", + index, phdr[index].p_memsz, phdr[index].p_filesz); + return RT_NULL; + } + if (!has_vstart) + { + vstart_addr = phdr[index].p_vaddr; + vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz; + has_vstart = RT_TRUE; + if (vend_addr < vstart_addr) + { + rt_kprintf("invalid elf: segment %d: p_vaddr: %d, p_memsz: %d\n", + index, phdr[index].p_vaddr, phdr[index].p_memsz); + return RT_NULL; + } + } + else + { + if (phdr[index].p_vaddr < vend_addr) + { + rt_kprintf("invalid elf: segment should be sorted and not overlapped\n"); + return RT_NULL; + } + if (phdr[index].p_vaddr > vend_addr + 16) + { + /* There should not be too much padding in the object files. */ + LOG_W("warning: too much padding before segment %d", index); + } + + vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz; + if (vend_addr < phdr[index].p_vaddr) + { + rt_kprintf("invalid elf: " + "segment %d address overflow\n", index); + return RT_NULL; + } + } + } + + module_size = vend_addr - vstart_addr; + LOG_D("module size: %d, vstart_addr: 0x%p", module_size, vstart_addr); + if (module_size == 0) + { + rt_kprintf("Module: size error\n"); + return -RT_ERROR; + } + + module->vstart_addr = vstart_addr; + module->nref = 0; + + /* allocate module space */ + module->mem_space = rt_malloc(module_size); + if (module->mem_space == RT_NULL) + { + rt_kprintf("Module: allocate space failed.\n"); + return -RT_ERROR; + } + module->mem_size = module_size; + + /* zero all space */ + rt_memset(module->mem_space, 0, module_size); + for (index = 0; index < elf_module->e_phnum; index++) + { + if (phdr[index].p_type == PT_LOAD) + { + rt_memcpy(module->mem_space + phdr[index].p_vaddr - vstart_addr, + (rt_uint8_t *)elf_module + phdr[index].p_offset, + phdr[index].p_filesz); + } + } + + /* set module entry */ + module->entry_addr = module->mem_space + elf_module->e_entry - vstart_addr; + + /* handle relocation section */ + for (index = 0; index < elf_module->e_shnum; index ++) + { + rt_uint32_t i, nr_reloc; + Elf32_Sym *symtab; + Elf32_Rel *rel; + rt_uint8_t *strtab; + static rt_bool_t unsolved = RT_FALSE; + + if (!IS_REL(shdr[index])) + continue; + + /* get relocate item */ + rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); + + /* locate .rel.plt and .rel.dyn section */ + symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + + shdr[shdr[index].sh_link].sh_offset); + strtab = (rt_uint8_t *)module_ptr + + shdr[shdr[shdr[index].sh_link].sh_link].sh_offset; + nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel)); + + /* relocate every items */ + for (i = 0; i < nr_reloc; i ++) + { + Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)]; + + LOG_D("relocate symbol %s shndx %d", strtab + sym->st_name, sym->st_shndx); + + if ((sym->st_shndx != SHT_NULL) ||(ELF_ST_BIND(sym->st_info) == STB_LOCAL)) + { + Elf32_Addr addr; + + addr = (Elf32_Addr)(module->mem_space + sym->st_value - vstart_addr); + dlmodule_relocate(module, rel, addr); + } + else if (!linked) + { + Elf32_Addr addr; + + LOG_D("relocate symbol: %s", strtab + sym->st_name); + /* need to resolve symbol in kernel symbol table */ + addr = dlmodule_symbol_find((const char *)(strtab + sym->st_name)); + if (addr == 0) + { + LOG_E("Module: can't find %s in kernel symbol table", strtab + sym->st_name); + unsolved = RT_TRUE; + } + else + { + dlmodule_relocate(module, rel, addr); + } + } + rel ++; + } + + if (unsolved) + return -RT_ERROR; + } + + /* construct module symbol table */ + for (index = 0; index < elf_module->e_shnum; index ++) + { + /* find .dynsym section */ + rt_uint8_t *shstrab; + shstrab = (rt_uint8_t *)module_ptr + + shdr[elf_module->e_shstrndx].sh_offset; + if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0) + break; + } + + /* found .dynsym section */ + if (index != elf_module->e_shnum) + { + int i, count = 0; + Elf32_Sym *symtab = RT_NULL; + rt_uint8_t *strtab = RT_NULL; + + symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); + strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset; + + for (i = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++) + { + if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && + (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC)) + count ++; + } + + module->symtab = (struct rt_module_symtab *)rt_malloc + (count * sizeof(struct rt_module_symtab)); + module->nsym = count; + for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++) + { + rt_size_t length; + + if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) || + (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC)) + continue; + + length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1; + + module->symtab[count].addr = + (void *)(module->mem_space + symtab[i].st_value - module->vstart_addr); + module->symtab[count].name = rt_malloc(length); + rt_memset((void *)module->symtab[count].name, 0, length); + rt_memcpy((void *)module->symtab[count].name, + strtab + symtab[i].st_name, + length); + count ++; + } + } + + return RT_EOK; +} + +rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr) +{ + rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0; + rt_uint32_t module_addr = 0, module_size = 0; + rt_uint8_t *ptr, *strtab, *shstrab; + + /* get the ELF image size */ + for (index = 0; index < elf_module->e_shnum; index ++) + { + /* text */ + if (IS_PROG(shdr[index]) && IS_AX(shdr[index])) + { + module_size += shdr[index].sh_size; + module_addr = shdr[index].sh_addr; + } + /* rodata */ + if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index])) + { + module_size += shdr[index].sh_size; + } + /* data */ + if (IS_PROG(shdr[index]) && IS_AW(shdr[index])) + { + module_size += shdr[index].sh_size; + } + /* bss */ + if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index])) + { + module_size += shdr[index].sh_size; + } + } + + /* no text, data and bss on image */ + if (module_size == 0) return RT_NULL; + + module->vstart_addr = 0; + + /* allocate module space */ + module->mem_space = rt_malloc(module_size); + if (module->mem_space == RT_NULL) + { + rt_kprintf("Module: allocate space failed.\n"); + return -RT_ERROR; + } + + /* zero all space */ + ptr = module->mem_space; + rt_memset(ptr, 0, module_size); + + /* load text and data section */ + for (index = 0; index < elf_module->e_shnum; index ++) + { + /* load text section */ + if (IS_PROG(shdr[index]) && IS_AX(shdr[index])) + { + rt_memcpy(ptr, + (rt_uint8_t *)elf_module + shdr[index].sh_offset, + shdr[index].sh_size); + LOG_D("load text 0x%x, size %d", ptr, shdr[index].sh_size); + ptr += shdr[index].sh_size; + } + + /* load rodata section */ + if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index])) + { + rt_memcpy(ptr, + (rt_uint8_t *)elf_module + shdr[index].sh_offset, + shdr[index].sh_size); + rodata_addr = (rt_uint32_t)ptr; + LOG_D("load rodata 0x%x, size %d, rodata 0x%x", ptr, + shdr[index].sh_size, *(rt_uint32_t *)data_addr); + ptr += shdr[index].sh_size; + } + + /* load data section */ + if (IS_PROG(shdr[index]) && IS_AW(shdr[index])) + { + rt_memcpy(ptr, + (rt_uint8_t *)elf_module + shdr[index].sh_offset, + shdr[index].sh_size); + data_addr = (rt_uint32_t)ptr; + LOG_D("load data 0x%x, size %d, data 0x%x", ptr, + shdr[index].sh_size, *(rt_uint32_t *)data_addr); + ptr += shdr[index].sh_size; + } + + /* load bss section */ + if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index])) + { + rt_memset(ptr, 0, shdr[index].sh_size); + bss_addr = (rt_uint32_t)ptr; + LOG_D("load bss 0x%x, size %d", ptr, shdr[index].sh_size); + } + } + + /* set module entry */ + module->entry_addr = (rt_dlmodule_entry_func_t)((rt_uint8_t *)module->mem_space + elf_module->e_entry - module_addr); + + /* handle relocation section */ + for (index = 0; index < elf_module->e_shnum; index ++) + { + rt_uint32_t i, nr_reloc; + Elf32_Sym *symtab; + Elf32_Rel *rel; + + if (!IS_REL(shdr[index])) + continue; + + /* get relocate item */ + rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); + + /* locate .dynsym and .dynstr */ + symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + + shdr[shdr[index].sh_link].sh_offset); + strtab = (rt_uint8_t *)module_ptr + + shdr[shdr[shdr[index].sh_link].sh_link].sh_offset; + shstrab = (rt_uint8_t *)module_ptr + + shdr[elf_module->e_shstrndx].sh_offset; + nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel)); + + /* relocate every items */ + for (i = 0; i < nr_reloc; i ++) + { + Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)]; + + LOG_D("relocate symbol: %s", strtab + sym->st_name); + + if (sym->st_shndx != STN_UNDEF) + { + Elf32_Addr addr = 0; + + if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) || + (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) + { + if (rt_strncmp((const char *)(shstrab + + shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0) + { + /* relocate rodata section */ + LOG_D("rodata"); + addr = (Elf32_Addr)(rodata_addr + sym->st_value); + } + else if (rt_strncmp((const char *) + (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0) + { + /* relocate bss section */ + LOG_D("bss"); + addr = (Elf32_Addr)bss_addr + sym->st_value; + } + else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), + ELF_DATA, 6) == 0) + { + /* relocate data section */ + LOG_D("data"); + addr = (Elf32_Addr)data_addr + sym->st_value; + } + + if (addr != 0) dlmodule_relocate(module, rel, addr); + } + else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) + { + addr = (Elf32_Addr)((rt_uint8_t *) module->mem_space - module_addr + sym->st_value); + + /* relocate function */ + dlmodule_relocate(module, rel, addr); + } + } + else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) + { + /* relocate function */ + dlmodule_relocate(module, rel, + (Elf32_Addr)((rt_uint8_t *) + module->mem_space + - module_addr + + sym->st_value)); + } + else + { + Elf32_Addr addr; + + if (ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX) + { + LOG_D("relocate symbol: %s", strtab + sym->st_name); + + /* need to resolve symbol in kernel symbol table */ + addr = dlmodule_symbol_find((const char *)(strtab + sym->st_name)); + if (addr != (Elf32_Addr)RT_NULL) + { + dlmodule_relocate(module, rel, addr); + LOG_D("symbol addr 0x%x", addr); + } + else + LOG_E("Module: can't find %s in kernel symbol table", + strtab + sym->st_name); + } + else + { + addr = (Elf32_Addr)((rt_uint8_t *) module->mem_space - module_addr + sym->st_value); + dlmodule_relocate(module, rel, addr); + } + } + + rel ++; + } + } + + return RT_EOK; +} diff --git a/src/module.h b/components/libc/libdl/dlelf.h similarity index 89% rename from src/module.h rename to components/libc/libdl/dlelf.h index 90d4dc9524..014ebe85c8 100644 --- a/src/module.h +++ b/components/libc/libdl/dlelf.h @@ -1,32 +1,15 @@ /* - * File : module.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Copyright (c) 2006-2018, RT-Thread Development Team * + * SPDX-License-Identifier: Apache-2.0 + * * Change Logs: - * Date Author Notes - * 2010-01-09 Bernard first version - * 2010-04-09 yi.qiu implement based on first version + * Date Author Notes + * 2018/08/29 Bernard first version */ -#ifndef __MODULE_H__ -#define __MODULE_H__ - -#include +#ifndef DL_ELF_H__ +#define DL_ELF_H__ typedef rt_uint8_t Elf_Byte; @@ -209,11 +192,19 @@ typedef struct #define R_ARM_V4BX 40 /* - * Relocation type for arm + * Relocation type for x86 */ +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 #define R_386_GLOB_DAT 6 -#define R_386_JUMP_SLOT 7 +#define R_386_JMP_SLOT 7 #define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 /* Program Header */ typedef struct @@ -274,4 +265,21 @@ typedef struct #define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ /* specific section attributes */ +#define IS_PROG(s) (s.sh_type == SHT_PROGBITS) +#define IS_NOPROG(s) (s.sh_type == SHT_NOBITS) +#define IS_REL(s) (s.sh_type == SHT_REL) +#define IS_RELA(s) (s.sh_type == SHT_RELA) +#define IS_ALLOC(s) (s.sh_flags == SHF_ALLOC) +#define IS_AX(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR)) +#define IS_AW(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE)) + +#define elf_module ((Elf32_Ehdr *)module_ptr) +#define shdr ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff)) +#define phdr ((Elf32_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff)) + +rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_ptr); +rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr); + +int dlmodule_relocate(struct rt_dlmodule *module, Elf32_Rel *rel, Elf32_Addr sym_val); + #endif diff --git a/components/libc/libdl/dlerror.c b/components/libc/libdl/dlerror.c index dd076412fe..ad9b630e4c 100644 --- a/components/libc/libdl/dlerror.c +++ b/components/libc/libdl/dlerror.c @@ -1,15 +1,11 @@ /* - * File : dlerror.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * Copyright (c) 2006-2018, RT-Thread Development Team * + * SPDX-License-Identifier: Apache-2.0 + * * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version + * Date Author Notes + * 2010-11-17 yi.qiu first version */ #include @@ -19,6 +15,4 @@ const char *dlerror(void) { return "TODO"; } - RTM_EXPORT(dlerror) - diff --git a/components/libc/libdl/dlfcn.h b/components/libc/libdl/dlfcn.h index 304ba5a777..55273a41eb 100644 --- a/components/libc/libdl/dlfcn.h +++ b/components/libc/libdl/dlfcn.h @@ -1,3 +1,13 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2010-11-17 yi.qiu first version + */ + #ifndef __DLFCN_H_ #define __DLFCN_H_ @@ -16,4 +26,3 @@ void *dlsym(void *handle, const char *symbol); int dlclose (void *handle); #endif - diff --git a/components/libc/libdl/dlmodule.c b/components/libc/libdl/dlmodule.c new file mode 100644 index 0000000000..57f2fdc384 --- /dev/null +++ b/components/libc/libdl/dlmodule.c @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/08/29 Bernard first version + */ + +#include + +#include "dlfcn.h" +#include "dlmodule.h" +#include "dlelf.h" + +#include + +#define DBG_SECTION_NAME "DLMD" +#define DBG_ENABLE // enable debug macro +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include // must after of DEBUG_ENABLE or some other options + +static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL; +static struct rt_module_symtab *_rt_module_symtab_end = RT_NULL; + +#if defined(__IAR_SYSTEMS_ICC__) /* for IAR compiler */ + #pragma section="RTMSymTab" +#endif + +/* set the name of module */ +static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path) +{ + int size; + struct rt_object *object; + const char *first, *end, *ptr; + + object = &(module->parent); + ptr = first = (char *)path; + end = path + rt_strlen(path); + + while (*ptr != '\0') + { + if (*ptr == '/') + first = ptr + 1; + if (*ptr == '.') + end = ptr - 1; + + ptr ++; + } + + size = end - first + 1; + if (size > RT_NAME_MAX) size = RT_NAME_MAX; + + rt_strncpy(object->name, first, size); + object->name[size] = '\0'; +} + +#define RT_MODULE_ARG_MAX 8 +static int _rt_module_split_arg(char *cmd, rt_size_t length, char *argv[]) +{ + int argc = 0; + char *ptr = cmd; + + while ((ptr - cmd) < length) + { + /* strip bank and tab */ + while ((*ptr == ' ' || *ptr == '\t') && (ptr - cmd) < length) + *ptr++ = '\0'; + /* check whether it's the end of line */ + if ((ptr - cmd) >= length) break; + + /* handle string with quote */ + if (*ptr == '"') + { + argv[argc++] = ++ptr; + + /* skip this string */ + while (*ptr != '"' && (ptr - cmd) < length) + if (*ptr ++ == '\\') ptr ++; + if ((ptr - cmd) >= length) break; + + /* skip '"' */ + *ptr ++ = '\0'; + } + else + { + argv[argc++] = ptr; + while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length) + ptr ++; + } + + if (argc >= RT_MODULE_ARG_MAX) break; + } + + return argc; +} + +/* invoked by main thread for exit */ +static void _dlmodule_exit(void) +{ + struct rt_dlmodule *module; + + module = dlmodule_self(); + if (!module) return; /* not a module thread */ + + rt_enter_critical(); + if (module->stat == RT_DLMODULE_STAT_RUNNING) + { + struct rt_object *object = RT_NULL; + struct rt_list_node *node = RT_NULL; + + /* set stat to closing */ + module->stat = RT_DLMODULE_STAT_CLOSING; + + /* suspend all threads in this module */ + for (node = module->object_list.next; node != &(module->object_list); node = node->next) + { + object = rt_list_entry(node, struct rt_object, list); + + if ((object->type & ~RT_Object_Class_Static) == RT_Object_Class_Thread) + { + rt_thread_t thread = (rt_thread_t)object; + + /* stop timer and suspend thread*/ + if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE || + (thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) + { + rt_timer_stop(&(thread->thread_timer)); + rt_thread_suspend(thread); + } + } + } + } + rt_exit_critical(); + + return; +} + +static void _dlmodule_thread_entry(void* parameter) +{ + int argc = 0; + char *argv[RT_MODULE_ARG_MAX]; + + struct rt_dlmodule *module = (struct rt_dlmodule*)parameter; + + if (module == RT_NULL || module->cmd_line == RT_NULL) + /* malloc for module_cmd_line failed. */ + return; + + if (module->cmd_line) + { + rt_memset(argv, 0x00, sizeof(argv)); + argc = _rt_module_split_arg((char *)module->cmd_line, rt_strlen(module->cmd_line), argv); + if (argc == 0) goto __exit; + } + + /* set status of module */ + module->stat = RT_DLMODULE_STAT_RUNNING; + + LOG_D("run main entry: 0x%p with %s", + module->entry_addr, + module->cmd_line); + + if (module->entry_addr) + module->entry_addr(argc, argv); + +__exit: + _dlmodule_exit(); + + return ; +} + +struct rt_dlmodule *dlmodule_create(void) +{ + struct rt_dlmodule *ret = RT_NULL; + + ret = (struct rt_dlmodule*) rt_object_allocate(RT_Object_Class_Module, "module"); + if (ret) + { + ret->stat = RT_DLMODULE_STAT_INIT; + rt_list_init(&(ret->object_list)); + } + + return ret; +} + +void dlmodule_destroy_subthread(struct rt_dlmodule *module, rt_thread_t thread) +{ + RT_ASSERT(thread->module_id == module); + + /* lock scheduler to prevent scheduling in cleanup function. */ + rt_enter_critical(); + + /* remove thread from thread_list (ready or defunct thread list) */ + rt_list_remove(&(thread->tlist)); + + if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE && + (thread->thread_timer.parent.type == (RT_Object_Class_Static | RT_Object_Class_Timer))) + { + /* release thread timer */ + rt_timer_detach(&(thread->thread_timer)); + } + + /* change stat */ + thread->stat = RT_THREAD_CLOSE; + + /* invoke thread cleanup */ + if (thread->cleanup != RT_NULL) + thread->cleanup(thread); + + rt_exit_critical(); + +#ifdef RT_USING_SIGNALS + rt_thread_free_sig(thread); +#endif + + if (thread->type & RT_Object_Class_Static) + { + /* detach object */ + rt_object_detach((rt_object_t)thread); + } +#ifdef RT_USING_HEAP + else + { + /* release thread's stack */ + RT_KERNEL_FREE(thread->stack_addr); + /* delete thread object */ + rt_object_delete((rt_object_t)thread); + } +#endif +} + +rt_err_t dlmodule_destroy(struct rt_dlmodule* module) +{ + int i; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* check parameter */ + if (module == RT_NULL) + return -RT_ERROR; + + /* can not destroy a running module */ + if (module->stat == RT_DLMODULE_STAT_RUNNING) + return -RT_EBUSY; + + /* do module cleanup */ + if (module->cleanup_func) + { + rt_enter_critical(); + module->cleanup_func(module); + rt_exit_critical(); + } + + // list_object(&(module->object_list)); + + /* cleanup for all kernel objects inside module*/ + { + struct rt_object *object = RT_NULL; + struct rt_list_node *node = RT_NULL; + + /* detach/delete all threads in this module */ + for (node = module->object_list.next; node != &(module->object_list); ) + { + int object_type; + + object = rt_list_entry(node, struct rt_object, list); + object_type = object->type & ~RT_Object_Class_Static; + + /* to next node */ + node = node->next; + + if (object->type & RT_Object_Class_Static) + { + switch (object_type) + { + case RT_Object_Class_Thread: + dlmodule_destroy_subthread(module, (rt_thread_t)object); + break; +#ifdef RT_USING_SEMAPHORE + case RT_Object_Class_Semaphore: + rt_sem_detach((rt_sem_t)object); + break; +#endif +#ifdef RT_USING_MUTEX + case RT_Object_Class_Mutex: + rt_mutex_detach((rt_mutex_t)object); + break; +#endif +#ifdef RT_USING_EVENT + case RT_Object_Class_Event: + rt_event_detach((rt_event_t)object); + break; +#endif +#ifdef RT_USING_MAILBOX + case RT_Object_Class_MailBox: + rt_mb_detach((rt_mailbox_t)object); + break; +#endif +#ifdef RT_USING_MESSAGEQUEUE + case RT_Object_Class_MessageQueue: + rt_mq_detach((rt_mq_t)object); + break; +#endif +#ifdef RT_USING_MEMHEAP + case RT_Object_Class_MemHeap: + rt_memheap_detach((struct rt_memheap*)object); + break; +#endif +#ifdef RT_USING_MEMPOOL + case RT_Object_Class_MemPool: + rt_mp_detach((struct rt_mempool*)object); + break; +#endif + case RT_Object_Class_Timer: + rt_timer_detach((rt_timer_t)object); + break; + default: + LOG_E("Unsupported oject type in module."); + break; + } + } + else + { + switch (object_type) + { + case RT_Object_Class_Thread: + dlmodule_destroy_subthread(module, (rt_thread_t)object); + break; +#ifdef RT_USING_SEMAPHORE + case RT_Object_Class_Semaphore: + rt_sem_delete((rt_sem_t)object); + break; +#endif +#ifdef RT_USING_MUTEX + case RT_Object_Class_Mutex: + rt_mutex_delete((rt_mutex_t)object); + break; +#endif +#ifdef RT_USING_EVENT + case RT_Object_Class_Event: + rt_event_delete((rt_event_t)object); + break; +#endif +#ifdef RT_USING_MAILBOX + case RT_Object_Class_MailBox: + rt_mb_delete((rt_mailbox_t)object); + break; +#endif +#ifdef RT_USING_MESSAGEQUEUE + case RT_Object_Class_MessageQueue: + rt_mq_delete((rt_mq_t)object); + break; +#endif +#ifdef RT_USING_MEMHEAP + /* no delete operation */ +#endif +#ifdef RT_USING_MEMPOOL + case RT_Object_Class_MemPool: + rt_mp_delete((struct rt_mempool*)object); + break; +#endif + case RT_Object_Class_Timer: + rt_timer_delete((rt_timer_t)object); + break; + default: + LOG_E("Unsupported oject type in module."); + break; + } + } + } + } + + if (module->cmd_line) rt_free(module->cmd_line); + /* release module symbol table */ + for (i = 0; i < module->nsym; i ++) + { + rt_free((void *)module->symtab[i].name); + } + if (module->symtab != RT_NULL) + { + rt_free(module->symtab); + } + + /* destory module */ + rt_free(module->mem_space); + /* delete module object */ + rt_object_delete((rt_object_t)module); + + return RT_EOK; +} + +struct rt_dlmodule *dlmodule_self(void) +{ + rt_thread_t tid; + struct rt_dlmodule *ret = RT_NULL; + + tid = rt_thread_self(); + if (tid) + { + ret = (struct rt_dlmodule*) tid->module_id; + } + + return ret; +} + +/* + * Compatible with old API + */ +struct rt_dlmodule *rt_module_self(void) +{ + return dlmodule_self(); +} + +struct rt_dlmodule* dlmodule_load(const char* filename) +{ + int fd, length = 0; + rt_err_t ret = RT_EOK; + rt_uint8_t *module_ptr = RT_NULL; + struct rt_dlmodule *module = RT_NULL; + + 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; + } + + /* 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 */ + rt_free(module_ptr); + + /* increase module reference count */ + module->nref ++; + + /* 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 (fd >= 0) close(fd); + if (module_ptr) rt_free(module_ptr); + if (module) dlmodule_destroy(module); + + return RT_NULL; +} + +struct rt_dlmodule* dlmodule_exec(const char* pgname, const char* cmd, int cmd_size) +{ + struct rt_dlmodule *module = RT_NULL; + + module = dlmodule_load(pgname); + if (module) + { + if (module->entry_addr) + { + /* exec this module */ + rt_thread_t tid; + + module->cmd_line = rt_strdup(cmd); + tid = rt_thread_create(module->parent.name, _dlmodule_thread_entry, (void*)module, + 2048, RT_THREAD_PRIORITY_MAX - 1, 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; + struct rt_dlmodule *module; + + module = dlmodule_self(); + if (!module) return; + + /* disable scheduling */ + rt_enter_critical(); + + /* module is not running */ + if (module->stat != RT_DLMODULE_STAT_RUNNING) + { + /* restore scheduling */ + rt_exit_critical(); + + return; + } + + /* set return code */ + module->ret_code = ret_code; + + /* do exit for this module */ + _dlmodule_exit(); + /* the stat of module was changed to CLOSING in _dlmodule_exit */ + + thread = module->main_thread; + if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE) + { + /* main thread already closed */ + rt_exit_critical(); + + return ; + } + + /* delete thread: insert to defunct thread list */ + rt_thread_delete(thread); + /* enable scheduling */ + rt_exit_critical(); +} + +rt_uint32_t dlmodule_symbol_find(const char *sym_str) +{ + /* find in kernel symbol table */ + struct rt_module_symtab *index; + + for (index = _rt_module_symtab_begin; index != _rt_module_symtab_end; index ++) + { + if (rt_strcmp(index->name, sym_str) == 0) + return (rt_uint32_t)index->addr; + } + + return 0; +} + +int rt_system_dlmodule_init(void) +{ +#if defined(__GNUC__) && !defined(__CC_ARM) + extern int __rtmsymtab_start; + extern int __rtmsymtab_end; + + _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start; + _rt_module_symtab_end = (struct rt_module_symtab *)&__rtmsymtab_end; +#elif defined (__CC_ARM) + extern int RTMSymTab$$Base; + extern int RTMSymTab$$Limit; + + _rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base; + _rt_module_symtab_end = (struct rt_module_symtab *)&RTMSymTab$$Limit; +#elif defined (__IAR_SYSTEMS_ICC__) + _rt_module_symtab_begin = __section_begin("RTMSymTab"); + _rt_module_symtab_end = __section_end("RTMSymTab"); +#endif + + return 0; +} +INIT_COMPONENT_EXPORT(rt_system_dlmodule_init); + +/** + * This function will find the specified module. + * + * @param name the name of module finding + * + * @return the module + */ +struct rt_dlmodule *dlmodule_find(const char *name) +{ + rt_object_t object; + struct rt_dlmodule *ret = RT_NULL; + + object = rt_object_find(name, RT_Object_Class_Module); + if (object) + { + ret = (struct rt_dlmodule*) object; + } + + return ret; +} +RTM_EXPORT(dlmodule_find); + +int list_symbols(void) +{ + extern int __rtmsymtab_start; + extern int __rtmsymtab_end; + + /* find in kernel symbol table */ + struct rt_module_symtab *index; + + for (index = _rt_module_symtab_begin; + index != _rt_module_symtab_end; + index ++) + { + rt_kprintf("%s => 0x%08x\n", index->name, index->addr); + } + + return 0; +} +MSH_CMD_EXPORT(list_symbols, list symbols information); + +int list_module(void) +{ + struct rt_dlmodule *module; + struct rt_list_node *list, *node; + struct rt_object_information *info; + + info = rt_object_get_information(RT_Object_Class_Module); + list = &info->object_list; + + rt_kprintf("module ref address \n"); + rt_kprintf("-------- -------- ------------\n"); + for (node = list->next; node != list; node = node->next) + { + module = (struct rt_dlmodule *)(rt_list_entry(node, struct rt_object, list)); + rt_kprintf("%-*.*s %-04d 0x%08x\n", + RT_NAME_MAX, RT_NAME_MAX, module->parent.name, module->nref, module->mem_space); + } + + return 0; +} +MSH_CMD_EXPORT(list_module, list modules in system); diff --git a/components/libc/libdl/dlmodule.h b/components/libc/libdl/dlmodule.h new file mode 100644 index 0000000000..9338260ce6 --- /dev/null +++ b/components/libc/libdl/dlmodule.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/08/11 Bernard the first version + */ + +#ifndef RT_DL_MODULE_H__ +#define RT_DL_MODULE_H__ + +#include + +#define RT_DLMODULE_STAT_INIT 0x00 +#define RT_DLMODULE_STAT_RUNNING 0x01 +#define RT_DLMODULE_STAT_CLOSING 0x02 +#define RT_DLMODULE_STAT_CLOSED 0x03 + +struct rt_dlmodule; +typedef void* rt_addr_t; + +typedef void (*rt_dlmodule_init_func_t)(struct rt_dlmodule *module); +typedef void (*rt_dlmodule_cleanup_func_t)(struct rt_dlmodule *module); +typedef int (*rt_dlmodule_entry_func_t)(int argc, char** argv); + +struct rt_dlmodule +{ + struct rt_object parent; + rt_list_t object_list; /* objects inside this module */ + + rt_uint8_t stat; /* status of module */ + + /* main thread of this module */ + struct rt_thread *main_thread; + int ret_code; /* the return code */ + + /* VMA base address for the first LOAD segment */ + rt_uint32_t vstart_addr; + + /* module entry, RT_NULL for dynamic library */ + rt_dlmodule_entry_func_t entry_addr; + char *cmd_line; /* command line */ + + rt_addr_t mem_space; /* memory space */ + rt_uint32_t mem_size; /* sizeof memory space */ + + /* init and clean function */ + rt_dlmodule_init_func_t init_func; + rt_dlmodule_cleanup_func_t cleanup_func; + + rt_uint16_t nref; /* reference count */ + + rt_uint16_t nsym; /* number of symbols in the module */ + struct rt_module_symtab *symtab; /* module symbol table */ +}; + +struct rt_dlmodule *dlmodule_create(void); +rt_err_t dlmodule_destroy(struct rt_dlmodule* module); + +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); +void dlmodule_exit(int ret_code); + +struct rt_dlmodule *dlmodule_find(const char *name); + +rt_uint32_t dlmodule_symbol_find(const char *sym_str); + +#endif diff --git a/components/libc/libdl/dlopen.c b/components/libc/libdl/dlopen.c index 6c89cb03c0..a8202ec607 100644 --- a/components/libc/libdl/dlopen.c +++ b/components/libc/libdl/dlopen.c @@ -1,11 +1,7 @@ /* - * File : dlopen.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * Copyright (c) 2006-2018, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes @@ -16,11 +12,13 @@ #include #include +#include "dlmodule.h" + #define MODULE_ROOT_DIR "/modules" void* dlopen(const char *filename, int flags) { - rt_module_t module; + struct rt_dlmodule *module; char *fullpath; const char*def_path = MODULE_ROOT_DIR; @@ -40,11 +38,21 @@ void* dlopen(const char *filename, int flags) fullpath = (char*)filename; /* absolute path, use it directly */ } - /* find in module list */ - module = rt_module_find(fullpath); + rt_enter_critical(); - if(module != RT_NULL) module->nref++; - else module = rt_module_open(fullpath); + /* find in module list */ + module = dlmodule_find(fullpath); + + if(module != RT_NULL) + { + rt_exit_critical(); + module->nref++; + } + else + { + rt_exit_critical(); + module = dlmodule_load(fullpath); + } if(fullpath != filename) { @@ -54,4 +62,3 @@ void* dlopen(const char *filename, int flags) return (void*)module; } RTM_EXPORT(dlopen); - diff --git a/components/libc/libdl/dlsym.c b/components/libc/libdl/dlsym.c index 36c7b01fce..ed0f183d83 100644 --- a/components/libc/libdl/dlsym.c +++ b/components/libc/libdl/dlsym.c @@ -1,37 +1,33 @@ /* - * File : dlsym.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * Copyright (c) 2006-2018, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version + * Date Author Notes + * 2010-11-17 yi.qiu first version */ #include #include +#include "dlmodule.h" + void* dlsym(void *handle, const char* symbol) { - int i; - rt_module_t module; - - RT_ASSERT(handle != RT_NULL); + int i; + struct rt_dlmodule *module; + + RT_ASSERT(handle != RT_NULL); - module = (rt_module_t)handle; + module = (struct rt_dlmodule *)handle; - for(i=0; insym; i++) - { - if (rt_strcmp(module->symtab[i].name, symbol) == 0) - return (void*)module->symtab[i].addr; - } + for(i=0; insym; i++) + { + if (rt_strcmp(module->symtab[i].name, symbol) == 0) + return (void*)module->symtab[i].addr; + } - return RT_NULL; + return RT_NULL; } - RTM_EXPORT(dlsym) - diff --git a/include/rtdef.h b/include/rtdef.h index f8d90ceadb..d18ced3a6f 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -1021,59 +1021,6 @@ struct rt_device_graphic_ops /*@}*/ #endif -#ifdef RT_USING_MODULE -/** - * @addtogroup Module - */ - -/*@{*/ - -/* - * module system - */ - -#define RT_MODULE_FLAG_WITHENTRY 0x00 /**< with entry point */ -#define RT_MODULE_FLAG_WITHOUTENTRY 0x01 /**< without entry point */ - -/** - * Application Module structure - */ -struct rt_module -{ - struct rt_object parent; /**< inherit from object */ - - rt_uint32_t vstart_addr; /**< VMA base address for the - first LOAD segment. */ - rt_uint8_t *module_space; /**< module memory space */ - - void *module_entry; /**< the entry address of module */ - rt_thread_t module_thread; /**< the main thread of module */ - - rt_uint8_t *module_cmd_line; /**< module command line */ - rt_uint32_t module_cmd_size; /**< the size of module command line */ - -#ifdef RT_USING_SLAB - /* module memory allocator */ - void *mem_list; /**< module's free memory list */ - void *page_array; /**< module's using pages */ - rt_uint32_t page_cnt; /**< module's using pages count */ -#endif - - rt_uint16_t nref; /**< reference count */ - - rt_uint16_t nsym; /**< number of symbol in the module */ - struct rt_module_symtab *symtab; /**< module symbol table */ - - rt_uint32_t user_data; /**< arch data in the module */ - - void (*module_init)(void); - void (*module_cleanup)(void); -}; -typedef struct rt_module *rt_module_t; - -/*@}*/ -#endif - /* definitions for libc */ #include "rtlibc.h" diff --git a/include/rtthread.h b/include/rtthread.h index 86a1664f83..4114866f6f 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -442,44 +442,6 @@ rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg); /**@}*/ #endif -#ifdef RT_USING_MODULE -/** - * @addtogroup Module - */ - -/**@{*/ - -/* - * module interface - */ -rt_module_t rt_module_load(const char *name, void *module_ptr); -rt_err_t rt_module_unload(rt_module_t module); -#ifdef RT_USING_DFS -rt_module_t rt_module_open(const char *filename); -rt_module_t rt_module_exec_cmd(const char *path, const char *cmd_line, int size); -#endif -void *rt_module_malloc(rt_size_t size); -void *rt_module_realloc(void *ptr, rt_size_t size); -void rt_module_free(rt_module_t module, void *addr); -rt_module_t rt_module_self(void); -rt_module_t rt_module_find(const char *name); - -#ifdef RT_USING_HOOK -void rt_module_load_sethook(void (*hook)(rt_module_t module)); -void rt_module_unload_sethook(void (*hook)(rt_module_t module)); -#endif - -void rt_module_init_object_container(struct rt_module *module); -rt_err_t rt_module_destroy(rt_module_t module); - -/* - * application module system initialization - */ -int rt_system_module_init(void); - -/**@}*/ -#endif - /* * interrupt service */ diff --git a/src/Kconfig b/src/Kconfig index f08a90f66b..d3889f4211 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -295,8 +295,4 @@ menu "Kernel Device Object" endmenu -config RT_USING_MODULE - bool "The dynamic module feature" - default n - endmenu diff --git a/src/idle.c b/src/idle.c index d6c2f98a49..1aca33d3e4 100644 --- a/src/idle.c +++ b/src/idle.c @@ -32,6 +32,10 @@ #include #include +#ifdef RT_USING_MODULE +#include +#endif + #if defined (RT_USING_HOOK) #ifndef RT_USING_IDLE_HOOK #define RT_USING_IDLE_HOOK @@ -158,7 +162,7 @@ void rt_thread_idle_excute(void) rt_base_t lock; rt_thread_t thread; #ifdef RT_USING_MODULE - rt_module_t module = RT_NULL; + struct rt_dlmodule *module = RT_NULL; #endif RT_DEBUG_NOT_IN_INTERRUPT; @@ -173,14 +177,10 @@ void rt_thread_idle_excute(void) struct rt_thread, tlist); #ifdef RT_USING_MODULE - /* get thread's parent module */ - module = (rt_module_t)thread->module_id; - - /* if the thread is module's main thread */ - if (module != RT_NULL && module->module_thread == thread) + module = (struct rt_dlmodule*)thread->module_id; + if (module) { - /* detach module's main thread */ - module->module_thread = RT_NULL; + dlmodule_destroy(module); } #endif /* remove defunct thread */ diff --git a/src/kservice.c b/src/kservice.c index fa82ccdd80..35444aa248 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -36,6 +36,10 @@ #include #include +#ifdef RT_USING_MODULE +#include +#endif + /* use precision */ #define RT_PRINTF_PRECISION @@ -1323,13 +1327,10 @@ void rt_assert_handler(const char *ex_string, const char *func, rt_size_t line) if (rt_assert_hook == RT_NULL) { #ifdef RT_USING_MODULE - if (rt_module_self() != RT_NULL) + if (dlmodule_self()) { - /* unload assertion module */ - rt_module_unload(rt_module_self()); - - /* re-schedule */ - rt_schedule(); + /* close assertion module */ + dlmodule_exit(-1); } else #endif diff --git a/src/module.c b/src/module.c deleted file mode 100644 index 89ab7735bd..0000000000 --- a/src/module.c +++ /dev/null @@ -1,1289 +0,0 @@ -/* - * File : module.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Change Logs: - * Date Author Notes - * 2010-01-09 Bernard first version - * 2010-04-09 yi.qiu implement based on first version - * 2010-10-23 yi.qiu implement module memory allocator - * 2011-05-25 yi.qiu implement module hook function - * 2011-06-23 yi.qiu rewrite module memory allocator - * 2012-11-23 Bernard using RT_DEBUG_LOG instead of rt_kprintf. - * 2012-11-28 Bernard remove rt_current_module and user - * can use rt_module_unload to remove a module. - * 2017-08-20 parai support intel 386 machine - */ - -#include -#include -#include - -#ifdef RT_USING_FINSH -#include -#endif - -#ifdef RT_USING_MODULE -#include "module.h" - -#define elf_module ((Elf32_Ehdr *)module_ptr) -#define shdr ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff)) -#define phdr ((Elf32_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff)) - -#define IS_PROG(s) (s.sh_type == SHT_PROGBITS) -#define IS_NOPROG(s) (s.sh_type == SHT_NOBITS) -#define IS_REL(s) (s.sh_type == SHT_REL) -#define IS_RELA(s) (s.sh_type == SHT_RELA) -#define IS_ALLOC(s) (s.sh_flags == SHF_ALLOC) -#define IS_AX(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR)) -#define IS_AW(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE)) - -#ifdef RT_USING_MODULE_STKSZ -#undef RT_USING_MODULE_STKSZ -#endif - -#ifndef RT_USING_MODULE_STKSZ -#define RT_USING_MODULE_STKSZ (4096 * 2) -#endif - -#ifndef RT_USING_MODULE_PRIO -#define RT_USING_MODULE_PRIO (RT_THREAD_PRIORITY_MAX - 2) -#endif - -static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL; -static struct rt_module_symtab *_rt_module_symtab_end = RT_NULL; - -#if defined(__IAR_SYSTEMS_ICC__) /* for IAR compiler */ - #pragma section="RTMSymTab" -#endif - -/** - * @ingroup SystemInit - * - * This function will initialize system module - */ -int rt_system_module_init(void) -{ -#if defined(__GNUC__) && !defined(__CC_ARM) - extern int __rtmsymtab_start; - extern int __rtmsymtab_end; - - _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start; - _rt_module_symtab_end = (struct rt_module_symtab *)&__rtmsymtab_end; -#elif defined (__CC_ARM) - extern int RTMSymTab$$Base; - extern int RTMSymTab$$Limit; - - _rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base; - _rt_module_symtab_end = (struct rt_module_symtab *)&RTMSymTab$$Limit; -#elif defined (__IAR_SYSTEMS_ICC__) - _rt_module_symtab_begin = __section_begin("RTMSymTab"); - _rt_module_symtab_end = __section_end("RTMSymTab"); -#endif - - return 0; -} -INIT_COMPONENT_EXPORT(rt_system_module_init); - -#ifdef RT_USING_FINSH -void list_symbol(void) -{ - /* find in kernel symbol table */ - struct rt_module_symtab *index; - - for (index = _rt_module_symtab_begin; - index != _rt_module_symtab_end; - index ++) - { - rt_kprintf("%s => 0x%08x\n", index->name, index->addr); - } - - return ; -} -FINSH_FUNCTION_EXPORT(list_symbol, list symbol for module); -MSH_CMD_EXPORT(list_symbol, list symbol for module); -#endif - -static rt_uint32_t rt_module_symbol_find(const char *sym_str) -{ - /* find in kernel symbol table */ - struct rt_module_symtab *index; - - for (index = _rt_module_symtab_begin; - index != _rt_module_symtab_end; - index ++) - { - if (rt_strcmp(index->name, sym_str) == 0) - return (rt_uint32_t)index->addr; - } - - return 0; -} - -/** - * This function will return self module object - * - * @return the self module object - */ -rt_module_t rt_module_self(void) -{ - rt_thread_t tid; - - tid = rt_thread_self(); - if (tid == RT_NULL) - return RT_NULL; - - /* return current module */ - return (rt_module_t)tid->module_id; -} -RTM_EXPORT(rt_module_self); - -static int rt_module_arm_relocate(struct rt_module *module, - Elf32_Rel *rel, - Elf32_Addr sym_val) -{ - Elf32_Addr *where, tmp; - Elf32_Sword addend, offset; - rt_uint32_t upper, lower, sign, j1, j2; - - where = (Elf32_Addr *)((rt_uint8_t *)module->module_space - + rel->r_offset - - module->vstart_addr); - switch (ELF32_R_TYPE(rel->r_info)) - { - case R_ARM_NONE: - break; - case R_ARM_ABS32: - *where += (Elf32_Addr)sym_val; - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n", - where, *where)); - break; - case R_ARM_PC24: - case R_ARM_PLT32: - case R_ARM_CALL: - case R_ARM_JUMP24: - addend = *where & 0x00ffffff; - if (addend & 0x00800000) - addend |= 0xff000000; - tmp = sym_val - (Elf32_Addr)where + (addend << 2); - tmp >>= 2; - *where = (*where & 0xff000000) | (tmp & 0x00ffffff); - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n", - where, *where)); - break; - case R_ARM_REL32: - *where += sym_val - (Elf32_Addr)where; - RT_DEBUG_LOG(RT_DEBUG_MODULE, - ("R_ARM_REL32: %x -> %x, sym %x, offset %x\n", - where, *where, sym_val, rel->r_offset)); - break; - case R_ARM_V4BX: - *where &= 0xf000000f; - *where |= 0x01a0f000; - break; -#ifdef MODULE_USING_386 - case R_386_GLOB_DAT: - case R_386_JUMP_SLOT: -#endif - case R_ARM_GLOB_DAT: - case R_ARM_JUMP_SLOT: - *where = (Elf32_Addr)sym_val; - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n", - where, *where, sym_val)); - break; -#if 0 /* To do */ - case R_ARM_GOT_BREL: - temp = (Elf32_Addr)sym_val; - *where = (Elf32_Addr)&temp; - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n", - where, *where, sym_val)); - break; -#endif -#ifdef MODULE_USING_386 - case R_386_RELATIVE: -#endif - case R_ARM_RELATIVE: - *where = (Elf32_Addr)sym_val + *where; - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n", - where, *where, sym_val)); - break; - case R_ARM_THM_CALL: - case R_ARM_THM_JUMP24: - upper = *(rt_uint16_t *)where; - lower = *(rt_uint16_t *)((Elf32_Addr)where + 2); - - sign = (upper >> 10) & 1; - j1 = (lower >> 13) & 1; - j2 = (lower >> 11) & 1; - offset = (sign << 24) | - ((~(j1 ^ sign) & 1) << 23) | - ((~(j2 ^ sign) & 1) << 22) | - ((upper & 0x03ff) << 12) | - ((lower & 0x07ff) << 1); - if (offset & 0x01000000) - offset -= 0x02000000; - offset += sym_val - (Elf32_Addr)where; - - if (!(offset & 1) || - offset <= (rt_int32_t)0xff000000 || - offset >= (rt_int32_t)0x01000000) - { - rt_kprintf("Module: Only Thumb addresses allowed\n"); - - return -1; - } - - sign = (offset >> 24) & 1; - j1 = sign ^ (~(offset >> 23) & 1); - j2 = sign ^ (~(offset >> 22) & 1); - *(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) | - (sign << 10) | - ((offset >> 12) & 0x03ff)); - *(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) | - (j1 << 13) | (j2 << 11) | - ((offset >> 1) & 0x07ff)); - upper = *(rt_uint16_t *)where; - lower = *(rt_uint16_t *)((Elf32_Addr)where + 2); - break; - default: - return -1; - } - - return 0; -} - -#ifdef RT_USING_HOOK -static void (*rt_module_load_hook)(rt_module_t module); -static void (*rt_module_unload_hook)(rt_module_t module); - -/** - * @addtogroup Hook - */ - -/**@{*/ - -/** - * This function will set a hook function, which will be invoked when module - * be loaded to system. - * - * @param hook the hook function - */ -void rt_module_load_sethook(void (*hook)(rt_module_t module)) -{ - rt_module_load_hook = hook; -} - -/** - * This function will set a hook function, which will be invoked when module - * be unloaded from system. - * - * @param hook the hook function - */ -void rt_module_unload_sethook(void (*hook)(rt_module_t module)) -{ - rt_module_unload_hook = hook; -} - -/**@}*/ -#endif - -static struct rt_module *_load_shared_object(const char *name, - void *module_ptr) -{ - rt_module_t module = RT_NULL; - rt_bool_t linked = RT_FALSE; - rt_uint32_t index, module_size = 0; - Elf32_Addr vstart_addr, vend_addr; - rt_bool_t has_vstart; - - RT_ASSERT(module_ptr != RT_NULL); - - if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0) - { - /* rtmlinker finished */ - linked = RT_TRUE; - } - - /* get the ELF image size */ - has_vstart = RT_FALSE; - vstart_addr = vend_addr = RT_NULL; - for (index = 0; index < elf_module->e_phnum; index++) - { - if (phdr[index].p_type != PT_LOAD) - continue; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("LOAD segment: %d, 0x%p, 0x%08x\n", - index, phdr[index].p_vaddr, phdr[index].p_memsz)); - - if (phdr[index].p_memsz < phdr[index].p_filesz) - { - rt_kprintf("invalid elf: segment %d: p_memsz: %d, p_filesz: %d\n", - index, phdr[index].p_memsz, phdr[index].p_filesz); - return RT_NULL; - } - if (!has_vstart) - { - vstart_addr = phdr[index].p_vaddr; - vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz; - has_vstart = RT_TRUE; - if (vend_addr < vstart_addr) - { - rt_kprintf("invalid elf: segment %d: p_vaddr: %d, p_memsz: %d\n", - index, phdr[index].p_vaddr, phdr[index].p_memsz); - return RT_NULL; - } - } - else - { - if (phdr[index].p_vaddr < vend_addr) - { - rt_kprintf("invalid elf: segment should be sorted and not overlapped\n"); - return RT_NULL; - } - if (phdr[index].p_vaddr > vend_addr + 16) - { - /* There should not be too much padding in the object files. */ - rt_kprintf("warning: too much padding before segment %d\n", index); - } - - vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz; - if (vend_addr < phdr[index].p_vaddr) - { - rt_kprintf("invalid elf: " - "segment %d address overflow\n", index); - return RT_NULL; - } - } - } - - module_size = vend_addr - vstart_addr; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("module size: %d, vstart_addr: 0x%p\n", - module_size, vstart_addr)); - - if (module_size == 0) - { - rt_kprintf("Module: size error\n"); - - return RT_NULL; - } - - /* allocate module */ - module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, - name); - if (!module) - return RT_NULL; - - module->vstart_addr = vstart_addr; - - module->nref = 0; - - /* allocate module space */ - module->module_space = rt_malloc(module_size); - if (module->module_space == RT_NULL) - { - rt_kprintf("Module: allocate space failed.\n"); - rt_object_delete(&(module->parent)); - - return RT_NULL; - } - - /* zero all space */ - rt_memset(module->module_space, 0, module_size); - - for (index = 0; index < elf_module->e_phnum; index++) - { - if (phdr[index].p_type == PT_LOAD) - { - rt_memcpy(module->module_space + phdr[index].p_vaddr - vstart_addr, - (rt_uint8_t *)elf_module + phdr[index].p_offset, - phdr[index].p_filesz); - } - } - - /* set module entry */ - module->module_entry = module->module_space - + elf_module->e_entry - vstart_addr; - - /* handle relocation section */ - for (index = 0; index < elf_module->e_shnum; index ++) - { - rt_uint32_t i, nr_reloc; - Elf32_Sym *symtab; - Elf32_Rel *rel; - rt_uint8_t *strtab; - static rt_bool_t unsolved = RT_FALSE; - - if (!IS_REL(shdr[index])) - continue; - - /* get relocate item */ - rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); - - /* locate .rel.plt and .rel.dyn section */ - symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + - shdr[shdr[index].sh_link].sh_offset); - strtab = (rt_uint8_t *)module_ptr + - shdr[shdr[shdr[index].sh_link].sh_link].sh_offset; - nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel)); - - /* relocate every items */ - for (i = 0; i < nr_reloc; i ++) - { - Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)]; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol %s shndx %d\n", - strtab + sym->st_name, - sym->st_shndx)); - - if ((sym->st_shndx != SHT_NULL) || - (ELF_ST_BIND(sym->st_info) == STB_LOCAL) -#ifdef MODULE_USING_386 - || ( (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) && (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) ) -#endif - ) - { - rt_module_arm_relocate(module, rel, - (Elf32_Addr)(module->module_space - + sym->st_value - - vstart_addr)); - } - else if (!linked) - { - Elf32_Addr addr; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n", - strtab + sym->st_name)); - - /* need to resolve symbol in kernel symbol table */ - addr = rt_module_symbol_find((const char *)(strtab + sym->st_name)); - if (addr == 0) - { - rt_kprintf("Module: can't find %s in kernel symbol table\n", - strtab + sym->st_name); - unsolved = RT_TRUE; - } - else - rt_module_arm_relocate(module, rel, addr); - } - rel ++; - } - - if (unsolved) - { - rt_object_delete(&(module->parent)); - - return RT_NULL; - } - } - - /* construct module symbol table */ - for (index = 0; index < elf_module->e_shnum; index ++) - { - /* find .dynsym section */ - rt_uint8_t *shstrab; - shstrab = (rt_uint8_t *)module_ptr + - shdr[elf_module->e_shstrndx].sh_offset; - if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0) - break; - } - - /* found .dynsym section */ - if (index != elf_module->e_shnum) - { - int i, count = 0; - Elf32_Sym *symtab = RT_NULL; - rt_uint8_t *strtab = RT_NULL; - - symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); - strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset; - - for (i = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++) - { - if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && - (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC)) - count ++; - } - - module->symtab = (struct rt_module_symtab *)rt_malloc - (count * sizeof(struct rt_module_symtab)); - module->nsym = count; - for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++) - { - rt_size_t length; - - if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) || - (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC)) - continue; - - length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1; - - module->symtab[count].addr = - (void *)(module->module_space + symtab[i].st_value - module->vstart_addr); - module->symtab[count].name = rt_malloc(length); - rt_memset((void *)module->symtab[count].name, 0, length); - rt_memcpy((void *)module->symtab[count].name, - strtab + symtab[i].st_name, - length); - count ++; - } - } - - return module; -} - -static struct rt_module* _load_relocated_object(const char *name, - void *module_ptr) -{ - rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0; - rt_uint32_t module_addr = 0, module_size = 0; - struct rt_module *module = RT_NULL; - rt_uint8_t *ptr, *strtab, *shstrab; - - /* get the ELF image size */ - for (index = 0; index < elf_module->e_shnum; index ++) - { - /* text */ - if (IS_PROG(shdr[index]) && IS_AX(shdr[index])) - { - module_size += shdr[index].sh_size; - module_addr = shdr[index].sh_addr; - } - /* rodata */ - if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index])) - { - module_size += shdr[index].sh_size; - } - /* data */ - if (IS_PROG(shdr[index]) && IS_AW(shdr[index])) - { - module_size += shdr[index].sh_size; - } - /* bss */ - if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index])) - { - module_size += shdr[index].sh_size; - } - } - - /* no text, data and bss on image */ - if (module_size == 0) - return RT_NULL; - - /* allocate module */ - module = (struct rt_module *) - rt_object_allocate(RT_Object_Class_Module, (const char *)name); - if (module == RT_NULL) - return RT_NULL; - - module->vstart_addr = 0; - - /* allocate module space */ - module->module_space = rt_malloc(module_size); - if (module->module_space == RT_NULL) - { - rt_kprintf("Module: allocate space failed.\n"); - rt_object_delete(&(module->parent)); - - return RT_NULL; - } - - /* zero all space */ - ptr = module->module_space; - rt_memset(ptr, 0, module_size); - - /* load text and data section */ - for (index = 0; index < elf_module->e_shnum; index ++) - { - /* load text section */ - if (IS_PROG(shdr[index]) && IS_AX(shdr[index])) - { - rt_memcpy(ptr, - (rt_uint8_t *)elf_module + shdr[index].sh_offset, - shdr[index].sh_size); - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load text 0x%x, size %d\n", - ptr, shdr[index].sh_size)); - ptr += shdr[index].sh_size; - } - - /* load rodata section */ - if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index])) - { - rt_memcpy(ptr, - (rt_uint8_t *)elf_module + shdr[index].sh_offset, - shdr[index].sh_size); - rodata_addr = (rt_uint32_t)ptr; - RT_DEBUG_LOG(RT_DEBUG_MODULE, - ("load rodata 0x%x, size %d, rodata 0x%x\n", - ptr, shdr[index].sh_size, *(rt_uint32_t *)data_addr)); - ptr += shdr[index].sh_size; - } - - /* load data section */ - if (IS_PROG(shdr[index]) && IS_AW(shdr[index])) - { - rt_memcpy(ptr, - (rt_uint8_t *)elf_module + shdr[index].sh_offset, - shdr[index].sh_size); - data_addr = (rt_uint32_t)ptr; - RT_DEBUG_LOG(RT_DEBUG_MODULE, - ("load data 0x%x, size %d, data 0x%x\n", - ptr, shdr[index].sh_size, *(rt_uint32_t *)data_addr)); - ptr += shdr[index].sh_size; - } - - /* load bss section */ - if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index])) - { - rt_memset(ptr, 0, shdr[index].sh_size); - bss_addr = (rt_uint32_t)ptr; - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load bss 0x%x, size %d,\n", - ptr, shdr[index].sh_size)); - } - } - - /* set module entry */ - module->module_entry = - (rt_uint8_t *)module->module_space + elf_module->e_entry - module_addr; - - /* handle relocation section */ - for (index = 0; index < elf_module->e_shnum; index ++) - { - rt_uint32_t i, nr_reloc; - Elf32_Sym *symtab; - Elf32_Rel *rel; - - if (!IS_REL(shdr[index])) - continue; - - /* get relocate item */ - rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); - - /* locate .dynsym and .dynstr */ - symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + - shdr[shdr[index].sh_link].sh_offset); - strtab = (rt_uint8_t *)module_ptr + - shdr[shdr[shdr[index].sh_link].sh_link].sh_offset; - shstrab = (rt_uint8_t *)module_ptr + - shdr[elf_module->e_shstrndx].sh_offset; - nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel)); - - /* relocate every items */ - for (i = 0; i < nr_reloc; i ++) - { - Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)]; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n", - strtab + sym->st_name)); - - if (sym->st_shndx != STN_UNDEF) - { - if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) || - (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) - { - if (rt_strncmp((const char *)(shstrab + - shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0) - { - /* relocate rodata section */ - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rodata\n")); - rt_module_arm_relocate(module, rel, - (Elf32_Addr)(rodata_addr + sym->st_value)); - } - else if (rt_strncmp((const char *) - (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0) - { - /* relocate bss section */ - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("bss\n")); - rt_module_arm_relocate(module, rel, - (Elf32_Addr)bss_addr + sym->st_value); - } - else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), - ELF_DATA, 6) == 0) - { - /* relocate data section */ - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("data\n")); - rt_module_arm_relocate(module, rel, - (Elf32_Addr)data_addr + sym->st_value); - } - } - else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) - { - /* relocate function */ - rt_module_arm_relocate(module, rel, - (Elf32_Addr)((rt_uint8_t *) - module->module_space - - module_addr - + sym->st_value)); - } - } - else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) - { - /* relocate function */ - rt_module_arm_relocate(module, rel, - (Elf32_Addr)((rt_uint8_t *) - module->module_space - - module_addr - + sym->st_value)); - } - else - { - Elf32_Addr addr; - - if (ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX) - { - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n", - strtab + sym->st_name)); - - /* need to resolve symbol in kernel symbol table */ - addr = rt_module_symbol_find((const char *)(strtab + sym->st_name)); - if (addr != (Elf32_Addr)RT_NULL) - { - rt_module_arm_relocate(module, rel, addr); - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("symbol addr 0x%x\n", - addr)); - } - else - rt_kprintf("Module: can't find %s in kernel symbol table\n", - strtab + sym->st_name); - } - else - { - rt_module_arm_relocate(module, rel, - (Elf32_Addr)((rt_uint8_t *) - module->module_space - - module_addr - + sym->st_value)); - } - } - rel ++; - } - } - - return module; -} - -#define RT_MODULE_ARG_MAX 8 -static int _rt_module_split_arg(char *cmd, rt_size_t length, char *argv[]) -{ - int argc = 0; - char *ptr = cmd; - - while ((ptr - cmd) < length) - { - /* strip bank and tab */ - while ((*ptr == ' ' || *ptr == '\t') && (ptr - cmd) < length) - *ptr++ = '\0'; - /* check whether it's the end of line */ - if ((ptr - cmd) >= length) break; - - /* handle string with quote */ - if (*ptr == '"') - { - argv[argc++] = ++ptr; - - /* skip this string */ - while (*ptr != '"' && (ptr - cmd) < length) - if (*ptr ++ == '\\') ptr ++; - if ((ptr - cmd) >= length) break; - - /* skip '"' */ - *ptr ++ = '\0'; - } - else - { - argv[argc++] = ptr; - while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length) - ptr ++; - } - - if (argc >= RT_MODULE_ARG_MAX) break; - } - - return argc; -} - -/* module main thread entry */ -static void module_main_entry(void *parameter) -{ - int argc; - char *argv[RT_MODULE_ARG_MAX]; - typedef int (*main_func_t)(int argc, char **argv); - - rt_module_t module = (rt_module_t) parameter; - if (module == RT_NULL) - return; - - if (module->module_cmd_line == RT_NULL && module->module_cmd_size != 0) - /* malloc for module_cmd_line failed. */ - return; - - /* FIXME: we should run some C++ initialize code before jump into the - * entry. */ - - if (module->module_cmd_line == RT_NULL) - { - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("run bare entry: 0x%p\n", - module->module_entry)); - ((main_func_t)module->module_entry)(0, RT_NULL); - return; - } - - rt_memset(argv, 0x00, sizeof(argv)); - argc = _rt_module_split_arg((char *)module->module_cmd_line, - module->module_cmd_size, argv); - if (argc == 0) - return; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("run main entry: 0x%p with %s\n", - module->module_entry, - module->module_cmd_line)); - /* do the main function */ - ((main_func_t)module->module_entry)(argc, argv); - return; -} - -/** - * This function will load a module with a main function from memory and create a - * main thread for it - * - * @param name the name of module, which shall be unique - * @param module_ptr the memory address of module image - * @argc the count of argument - * @argd the argument data, which should be a - * - * @return the module object - */ -rt_module_t rt_module_do_main(const char *name, - void *module_ptr, - const char *cmd_line, - int line_size) -{ - rt_module_t module; - - RT_DEBUG_NOT_IN_INTERRUPT; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_load: %s\n", name)); - - /* 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"); - - return RT_NULL; - } - - /* check ELF class */ - if (elf_module->e_ident[EI_CLASS] != ELFCLASS32) - { - rt_kprintf("Module: ELF class error\n"); - - return RT_NULL; - } - - if (elf_module->e_type == ET_REL) - { - module = _load_relocated_object(name, module_ptr); - } - else if (elf_module->e_type == ET_DYN) - { - module = _load_shared_object(name, module_ptr); - } - else - { - rt_kprintf("Module: unsupported elf type\n"); - - return RT_NULL; - } - - if (module == RT_NULL) - return RT_NULL; - - if (line_size && cmd_line) - { - /* set module argument */ - module->module_cmd_line = (rt_uint8_t *)rt_malloc(line_size + 1); - if (module->module_cmd_line) - { - rt_memcpy(module->module_cmd_line, cmd_line, line_size); - module->module_cmd_line[line_size] = '\0'; - } - module->module_cmd_size = line_size; - } - else - { - /* initialize an empty command */ - module->module_cmd_line = RT_NULL; - module->module_cmd_size = 0; - } - - /* increase module reference count */ - module->nref ++; - - if (elf_module->e_entry != 0) - { - /* create module thread */ - module->module_thread = rt_thread_create(name, - module_main_entry, module, - RT_USING_MODULE_STKSZ, - RT_USING_MODULE_PRIO, 10); - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n", - module->module_entry)); - - /* set module id */ - module->module_thread->module_id = (void *)module; - module->parent.flag = RT_MODULE_FLAG_WITHENTRY; - - /* startup module thread */ - rt_thread_startup(module->module_thread); - } - else - { - /* without entry point */ - module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY; - } - -#ifdef RT_USING_HOOK - if (rt_module_load_hook != RT_NULL) - { - rt_module_load_hook(module); - } -#endif - - return module; -} - -/** - * This function will load a module from memory and create a thread for it - * - * @param name the name of module, which shall be unique - * @param module_ptr the memory address of module image - * - * @return the module object - */ -rt_module_t rt_module_load(const char *name, void *module_ptr) -{ - return rt_module_do_main(name, module_ptr, RT_NULL, 0); -} - -#ifdef RT_USING_DFS -#include - -static char *_module_name(const char *path) -{ - const char *first, *end, *ptr; - char *name; - int size; - - ptr = (char *)path; - first = ptr; - end = path + rt_strlen(path); - - while (*ptr != '\0') - { - if (*ptr == '/') - first = ptr + 1; - if (*ptr == '.') - end = ptr - 1; - - ptr ++; - } - - size = end - first + 1; - name = rt_malloc(size); - rt_strncpy(name, first, size); - name[size] = '\0'; - - return name; -} - -/** - * This function will load a module from a file - * - * @param path the full path of application module - * - * @return the module object - */ -rt_module_t rt_module_open(const char *path) -{ - int fd, length; - struct rt_module *module; - struct stat s; - char *buffer, *offset_ptr; - char *name; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* check parameters */ - RT_ASSERT(path != RT_NULL); - - if (stat(path, &s) != 0) - { - rt_kprintf("Module: access %s failed\n", path); - - return RT_NULL; - } - buffer = (char *)rt_malloc(s.st_size); - if (buffer == RT_NULL) - { - rt_kprintf("Module: out of memory\n"); - - return RT_NULL; - } - - offset_ptr = buffer; - fd = open(path, O_RDONLY, 0); - if (fd < 0) - { - rt_kprintf("Module: open %s failed\n", path); - rt_free(buffer); - - return RT_NULL; - } - - do - { - length = read(fd, offset_ptr, 4096); - if (length > 0) - { - offset_ptr += length; - } - }while (length > 0); - - /* close fd */ - close(fd); - - if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size) - { - rt_kprintf("Module: read file failed\n"); - rt_free(buffer); - - return RT_NULL; - } - - name = _module_name(path); - module = rt_module_load(name, (void *)buffer); - rt_free(buffer); - rt_free(name); - - return module; -} - -/** - * This function will do a excutable program with main function and parameters. - * - * @param path the full path of application module - * @param cmd_line the command line of program - * @param size the size of command line of program - * - * @return the module object - */ -rt_module_t rt_module_exec_cmd(const char *path, const char *cmd_line, int size) -{ - struct stat s; - int fd, length; - char *name, *buffer, *offset_ptr; - struct rt_module *module = RT_NULL; - - name = buffer = RT_NULL; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* check parameters */ - RT_ASSERT(path != RT_NULL); - - /* get file size */ - if (stat(path, &s) != 0) - { - rt_kprintf("Module: access %s failed\n", path); - goto __exit; - } - - /* allocate buffer to save program */ - offset_ptr = buffer = (char *)rt_malloc(s.st_size); - if (buffer == RT_NULL) - { - rt_kprintf("Module: out of memory\n"); - goto __exit; - } - - fd = open(path, O_RDONLY, 0); - if (fd < 0) - { - rt_kprintf("Module: open %s failed\n", path); - goto __exit; - } - - do - { - length = read(fd, offset_ptr, 4096); - if (length > 0) - { - offset_ptr += length; - } - }while (length > 0); - /* close fd */ - close(fd); - - if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size) - { - rt_kprintf("Module: read file failed\n"); - goto __exit; - } - - /* get module */ - name = _module_name(path); - /* execute module */ - module = rt_module_do_main(name, (void *)buffer, cmd_line, size); - -__exit: - rt_free(buffer); - rt_free(name); - - return module; -} - -#if defined(RT_USING_FINSH) -#include -FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file); -#endif - -#endif - -/** - * This function will destroy a module and release its resource. - * - * @param module the module to be destroyed. - * - * @return the operation status, RT_EOK on OK; -RT_ERROR on error - */ -rt_err_t rt_module_destroy(rt_module_t module) -{ - int i; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* check parameter */ - RT_ASSERT(module != RT_NULL); - RT_ASSERT(module->nref == 0); - RT_ASSERT(rt_object_get_type(&module->parent) == RT_Object_Class_Module); - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_destroy: %8.*s\n", - RT_NAME_MAX, module->parent.name)); - - /* module has entry point */ - if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY)) - { - /* delete command line */ - if (module->module_cmd_line != RT_NULL) - { - rt_free(module->module_cmd_line); - } - } - - /* release module space memory */ - rt_free(module->module_space); - - /* release module symbol table */ - for (i = 0; i < module->nsym; i ++) - { - rt_free((void *)module->symtab[i].name); - } - if (module->symtab != RT_NULL) - rt_free(module->symtab); - - /* delete module object */ - rt_object_delete((rt_object_t)module); - - return RT_EOK; -} - -/** - * This function will unload a module from memory and release resources - * - * @param module the module to be unloaded - * - * @return the operation status, RT_EOK on OK; -RT_ERROR on error - */ -rt_err_t rt_module_unload(rt_module_t module) -{ - RT_DEBUG_NOT_IN_INTERRUPT; - - /* check parameter */ - if (module == RT_NULL) - return -RT_ERROR; - - rt_enter_critical(); - /* invoke module cleanup */ - rt_exit_critical(); - -#ifdef RT_USING_HOOK - if (rt_module_unload_hook != RT_NULL) - { - rt_module_unload_hook(module); - } -#endif - - return RT_EOK; -} - -/** - * This function will find the specified module. - * - * @param name the name of module finding - * - * @return the module - */ -rt_module_t rt_module_find(const char *name) -{ - struct rt_object_information *information; - struct rt_object *object; - struct rt_list_node *node; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* enter critical */ - rt_enter_critical(); - - /* try to find device object */ - information = rt_object_get_information(RT_Object_Class_Module); - RT_ASSERT(information != RT_NULL); - for (node = information->object_list.next; - node != &(information->object_list); - node = node->next) - { - object = rt_list_entry(node, struct rt_object, list); - if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0) - { - /* leave critical */ - rt_exit_critical(); - - return (rt_module_t)object; - } - } - - /* leave critical */ - rt_exit_critical(); - - /* not found */ - return RT_NULL; -} -RTM_EXPORT(rt_module_find); - -#endif diff --git a/src/object.c b/src/object.c index b09af9ddee..e9a2b99246 100644 --- a/src/object.c +++ b/src/object.c @@ -32,6 +32,10 @@ #include #include +#ifdef RT_USING_MODULE +#include +#endif + /* * define object_info for the number of rt_object_container items. */ @@ -111,7 +115,7 @@ static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)}, #ifdef RT_USING_MODULE /* initialize object container - module */ - {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_module)}, + {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)}, #endif }; @@ -251,6 +255,9 @@ void rt_object_init(struct rt_object *object, { register rt_base_t temp; struct rt_object_information *information; +#ifdef RT_USING_MODULE + struct rt_dlmodule *module = dlmodule_self(); +#endif /* get object information */ information = rt_object_get_information(type); @@ -269,8 +276,18 @@ void rt_object_init(struct rt_object *object, /* lock interrupt */ temp = rt_hw_interrupt_disable(); - /* insert object into information object list */ - rt_list_insert_after(&(information->object_list), &(object->list)); +#ifdef RT_USING_MODULE + if (module) + { + rt_list_insert_after(&(module->object_list), &(object->list)); + object->module_id = (void *)module; + } + else +#endif + { + /* insert object into information object list */ + rt_list_insert_after(&(information->object_list), &(object->list)); + } /* unlock interrupt */ rt_hw_interrupt_enable(temp); @@ -318,6 +335,9 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) struct rt_object *object; register rt_base_t temp; struct rt_object_information *information; +#ifdef RT_USING_MODULE + struct rt_dlmodule *module = dlmodule_self(); +#endif RT_DEBUG_NOT_IN_INTERRUPT; @@ -332,6 +352,9 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) return RT_NULL; } + /* clean memory data of object */ + rt_memset(object, 0x0, information->object_size); + /* initialize object's parameters */ /* set object type */ @@ -340,14 +363,6 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) /* set object flag */ object->flag = 0; -#ifdef RT_USING_MODULE - if (rt_module_self() != RT_NULL) - { - object->flag |= RT_OBJECT_FLAG_MODULE; - } - object->module_id = (void *)rt_module_self(); -#endif - /* copy name */ rt_strncpy(object->name, name, RT_NAME_MAX); @@ -356,8 +371,18 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) /* lock interrupt */ temp = rt_hw_interrupt_disable(); - /* insert object into information object list */ - rt_list_insert_after(&(information->object_list), &(object->list)); +#ifdef RT_USING_MODULE + if (module) + { + rt_list_insert_after(&(module->object_list), &(object->list)); + object->module_id = (void *)module; + } + else +#endif + { + /* insert object into information object list */ + rt_list_insert_after(&(information->object_list), &(object->list)); + } /* unlock interrupt */ rt_hw_interrupt_enable(temp); diff --git a/src/thread.c b/src/thread.c index b3d91b30d0..7febf32082 100644 --- a/src/thread.c +++ b/src/thread.c @@ -185,10 +185,6 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, 0, RT_TIMER_FLAG_ONE_SHOT); -#ifdef RT_USING_MODULE - thread->module_id = RT_NULL; -#endif - /* initialize signal */ #ifdef RT_USING_SIGNALS thread->sig_mask = 0x00;