[Kernel] More better support for module.

This commit is contained in:
Bernard Xiong 2015-08-03 16:02:24 +08:00
parent db73a31ec8
commit abd19b8dd7
3 changed files with 297 additions and 223 deletions

View File

@ -892,7 +892,8 @@ enum
RTGRAPHIC_PIXEL_FORMAT_BGR565 = RTGRAPHIC_PIXEL_FORMAT_RGB565P,
RTGRAPHIC_PIXEL_FORMAT_RGB666,
RTGRAPHIC_PIXEL_FORMAT_RGB888,
RTGRAPHIC_PIXEL_FORMAT_ARGB888
RTGRAPHIC_PIXEL_FORMAT_ARGB888,
RTGRAPHIC_PIXEL_FORMAT_ABGR888,
};
/**
@ -965,6 +966,8 @@ 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 */

View File

@ -33,6 +33,10 @@
#include <rtthread.h>
#include <rtm.h>
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif
#ifdef RT_USING_MODULE
#include "module.h"
@ -48,6 +52,18 @@
#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
#ifdef RT_USING_SLAB
#define PAGE_COUNT_MAX 256
@ -75,6 +91,10 @@ static struct rt_semaphore mod_sem;
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
*
@ -94,6 +114,9 @@ int rt_system_module_init(void)
_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_begin("RTMSymTab");
#endif
#ifdef RT_USING_SLAB
@ -104,6 +127,25 @@ int rt_system_module_init(void)
}
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\n", index->name);
}
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 */
@ -145,7 +187,9 @@ static int rt_module_arm_relocate(struct rt_module *module,
Elf32_Sword addend, offset;
rt_uint32_t upper, lower, sign, j1, j2;
where = (Elf32_Addr *)((rt_uint8_t *)module->module_space + rel->r_offset);
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:
@ -351,10 +395,11 @@ void rt_module_unload_sethook(void (*hook)(rt_module_t module))
static struct rt_module *_load_shared_object(const char *name,
void *module_ptr)
{
rt_uint8_t *ptr = RT_NULL;
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);
@ -365,11 +410,61 @@ static struct rt_module *_load_shared_object(const char *name,
}
/* 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)
module_size += phdr[index].p_memsz;
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)
{
@ -384,6 +479,8 @@ static struct rt_module *_load_shared_object(const char *name,
if (!module)
return RT_NULL;
module->vstart_addr = vstart_addr;
module->nref = 0;
/* allocate module space */
@ -397,21 +494,21 @@ static struct rt_module *_load_shared_object(const char *name,
}
/* zero all space */
ptr = module->module_space;
rt_memset(ptr, 0, module_size);
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(ptr + phdr[index].p_paddr,
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;
module->module_entry = module->module_space
+ elf_module->e_entry - vstart_addr;
/* handle relocation section */
for (index = 0; index < elf_module->e_shnum; index ++)
@ -448,7 +545,9 @@ static struct rt_module *_load_shared_object(const char *name,
(ELF_ST_BIND(sym->st_info) == STB_LOCAL))
{
rt_module_arm_relocate(module, rel,
(Elf32_Addr)(module->module_space + sym->st_value));
(Elf32_Addr)(module->module_space
+ sym->st_value
- vstart_addr));
}
else if (!linked)
{
@ -578,6 +677,8 @@ static struct rt_module* _load_relocated_object(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)
@ -710,8 +811,11 @@ static struct rt_module* _load_relocated_object(const char *name,
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));
rt_module_arm_relocate(module, rel,
(Elf32_Addr)((rt_uint8_t *)
module->module_space
- module_addr
+ sym->st_value));
}
else
{
@ -736,8 +840,11 @@ static struct rt_module* _load_relocated_object(const char *name,
}
else
{
rt_module_arm_relocate(module, rel, (Elf32_Addr)((rt_uint8_t*)
module->module_space - module_addr + sym->st_value));
rt_module_arm_relocate(module, rel,
(Elf32_Addr)((rt_uint8_t*)
module->module_space
- module_addr
+ sym->st_value));
}
}
rel ++;
@ -747,110 +854,6 @@ static struct rt_module* _load_relocated_object(const char *name,
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)
{
rt_module_t module;
RT_DEBUG_NOT_IN_INTERRUPT;
RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_load: %s ,", 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;
/* init module object container */
rt_module_init_object_container(module);
/* 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)
{
#ifdef RT_USING_SLAB
/* init module memory allocator */
module->mem_list = RT_NULL;
/* create page array */
module->page_array =
(void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
module->page_cnt = 0;
#endif
/* create module thread */
module->module_thread = rt_thread_create(name,
(void(*)(void *))module->module_entry, RT_NULL,
2048, RT_THREAD_PRIORITY_MAX - 2, 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;
}
#define RT_MODULE_ARG_MAX 8
static int _rt_module_split_arg(char* cmd, rt_size_t length, char* argv[])
{
@ -890,6 +893,7 @@ static int _rt_module_split_arg(char* cmd, rt_size_t length, char* argv[])
return argc;
}
/* module main thread entry */
static void module_main_entry(void* parameter)
{
@ -898,12 +902,33 @@ static void module_main_entry(void* parameter)
typedef int (*main_func_t)(int argc, char** argv);
rt_module_t module = (rt_module_t) parameter;
if (module == RT_NULL || module->module_cmd_line == RT_NULL) return;
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 ;
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;
@ -920,13 +945,16 @@ static void module_main_entry(void* parameter)
*
* @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 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 ,", name));
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 &&
@ -941,6 +969,7 @@ rt_module_t rt_module_do_main(const char *name, void *module_ptr, const char* cm
if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
{
rt_kprintf("Module: ELF class error\n");
return RT_NULL;
}
@ -954,7 +983,8 @@ rt_module_t rt_module_do_main(const char *name, void *module_ptr, const char* cm
}
else
{
rt_kprintf("Module: unsupported excutable program\n");
rt_kprintf("Module: unsupported elf type\n");
return RT_NULL;
}
@ -964,6 +994,24 @@ rt_module_t rt_module_do_main(const char *name, void *module_ptr, const char* cm
/* init module object container */
rt_module_init_object_container(module);
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 ++;
@ -979,22 +1027,20 @@ rt_module_t rt_module_do_main(const char *name, void *module_ptr, const char* cm
module->page_cnt = 0;
#endif
/* set module argument */
module->module_cmd_line = (rt_uint8_t*)rt_malloc(line_size + 1);
rt_memcpy(module->module_cmd_line, cmd_line, line_size);
module->module_cmd_line[line_size] = '\0';
module->module_cmd_size = line_size;
/* create module thread */
module->module_thread = rt_thread_create(name,
module_main_entry, module,
2048, RT_THREAD_PRIORITY_MAX - 2, 10);
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 main thread */
/* startup module thread */
rt_thread_startup(module->module_thread);
}
else
@ -1013,6 +1059,19 @@ rt_module_t rt_module_do_main(const char *name, void *module_ptr, const char* cm
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 <dfs_posix.h>
@ -1224,7 +1283,7 @@ rt_err_t rt_module_destroy(rt_module_t module)
{
#ifdef RT_USING_SEMAPHORE
/* delete semaphores */
list = &module->module_object[RT_Object_Class_Thread].object_list;
list = &module->module_object[RT_Object_Class_Semaphore].object_list;
while (list->next != list)
{
object = rt_list_entry(list->next, struct rt_object, list);
@ -1959,8 +2018,8 @@ void list_mempage(const char *name)
}
}
FINSH_FUNCTION_EXPORT(list_mempage, list module using memory page information)
#endif
#endif
#endif /* RT_USING_FINSH */
#endif /* RT_USING_SLAB */
#endif

View File

@ -222,7 +222,19 @@ typedef struct
} Elf32_Phdr;
/* p_type */
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_TLS 7
#define PT_NUM 8
#define PT_LOOS 0x60000000
#define PT_HIOS 0x6fffffff
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
/* p_flags */
#define PF_X 1