494 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			494 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdio.h>
 | ||
|  
 | ||
|  
 | ||
| /**
 | ||
|  * hello.c
 | ||
|  */
 | ||
|  
 | ||
|  
 | ||
| #include <stdlib.h>
 | ||
| #include <string.h>
 | ||
| #include <elf.h> 
 | ||
| #include <errno.h>
 | ||
| #include "rtthread.h"
 | ||
|  
 | ||
|  
 | ||
|  
 | ||
| //#define FILE     ft_file_struct
 | ||
| //#define fclose   ft_if_fclose
 | ||
| //#define fopen    ft_if_fopen
 | ||
| //#define fread    ft_if_fread
 | ||
| //#define fseek    ft_if_fseek
 | ||
| //#define ftell    ft_if_ftell
 | ||
|  
 | ||
| 
 | ||
| 
 | ||
|  
 | ||
| 
 | ||
|  
 | ||
| static appm_list_struct g_app_list={0};
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| //找到一个空的app结构体
 | ||
| static app_struct *appm_new(void)
 | ||
| {
 | ||
| 	if(g_app_list.used<APPM_LIST_MAXLEN)
 | ||
| 	{
 | ||
| 		for(int i=0;i<APPM_LIST_MAXLEN;i++)
 | ||
| 		{
 | ||
| 			app_struct *ptr=&g_app_list.app[i];
 | ||
| 			if(ptr->exe_addr==0)
 | ||
| 			{
 | ||
| 				g_app_list.used++;
 | ||
| 				return ptr;
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| static int appm_delete (app_struct *app)
 | ||
| {
 | ||
| 	if(app==0) return -1;
 | ||
|     for(int i=0;i<APPM_LIST_MAXLEN;i++)
 | ||
|     {
 | ||
|         app_struct *ptr=&g_app_list.app[i];
 | ||
|         if(ptr==app)
 | ||
|         {
 | ||
|             memset(ptr,0,sizeof(app_struct));
 | ||
|             g_app_list.used--;
 | ||
|             return 0;
 | ||
|         }
 | ||
|     }
 | ||
| 	return -1;
 | ||
| }
 | ||
| 
 | ||
| app_struct * appm_find (char *name)
 | ||
| {
 | ||
|     for(int i=0;i<APPM_LIST_MAXLEN;i++)
 | ||
|     {
 | ||
|         app_struct *ptr=&g_app_list.app[i];
 | ||
|         if(strcmp(ptr->app_info->name,name)==0)
 | ||
|         {
 | ||
|             return ptr;
 | ||
|         }
 | ||
|     }
 | ||
| 	return 0;
 | ||
| }
 | ||
| 
 | ||
| app_struct *appm_get(int index)
 | ||
| {
 | ||
| 	if(index>=0&&index<APPM_LIST_MAXLEN)
 | ||
| 	{
 | ||
| 		if(g_app_list.app[index].exe_addr)
 | ||
| 			return &g_app_list.app[index];
 | ||
| 		else
 | ||
| 			return 0;
 | ||
| 	}
 | ||
| 	return 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 获取当前正在运行的app数目
 | ||
| int appm_get_running_num(void)
 | ||
| {
 | ||
|     int ret=0;
 | ||
|     for(int i=0;i<APPM_LIST_MAXLEN;i++)
 | ||
|     {
 | ||
|         app_struct *ptr=&g_app_list.app[i];
 | ||
|         if(ptr->run_state) ret++;
 | ||
|     }
 | ||
| 	return ret;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
|  
 | ||
| /**elf 文件头和section表解析和检查***/
 | ||
| static int check_elf_head(app_struct * app )
 | ||
| {
 | ||
| 	if(app==0) return -1;
 | ||
| 	FILE *file_elf = app->file;
 | ||
| 	if(file_elf==0) return -1;
 | ||
| 	int i = 0;
 | ||
| 	int MagNum = 0;
 | ||
| 	unsigned long  file_size = 0;
 | ||
| 	int sechnum = 0;
 | ||
| 	uint32_t symsize = 0;
 | ||
| 	uint32_t symoff = 0;
 | ||
| 	uint32_t nSyms = 0,kk=0;
 | ||
| 	Elf32_Ehdr *Elf_header = malloc(sizeof(Elf32_Ehdr));
 | ||
|  
 | ||
|  
 | ||
| 	/*文件大小*/
 | ||
| 	fseek(file_elf,0,SEEK_END);
 | ||
| 	file_size = ftell(file_elf);
 | ||
| 	fseek(file_elf,0,SEEK_SET);
 | ||
| 	printf("file total size is:%ld bytes\r\n",file_size);
 | ||
| 	fread(Elf_header,sizeof(Elf32_Ehdr),1,file_elf);	
 | ||
| 
 | ||
| 	
 | ||
| 	/**确认是否为elf格式**/
 | ||
| 	if((Elf_header->e_ident[EI_MAG0] == ELFMAG0) && (Elf_header->e_ident[EI_MAG1] == ELFMAG1) \
 | ||
| 		&& (Elf_header->e_ident[EI_MAG2] == ELFMAG2) && (Elf_header->e_ident[EI_MAG3] == ELFMAG3))
 | ||
| 	{	
 | ||
| 		printf("This is ELF file!\r\n");
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		printf("NOT ELF file!\r\n");
 | ||
| 		free(Elf_header);
 | ||
| 		return -1;
 | ||
| 	}
 | ||
| 	
 | ||
| 	
 | ||
| 	free(Elf_header);
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	return 0;
 | ||
| }
 | ||
|  
 | ||
|  
 | ||
| /* 加载elf文件segment 到内存中 */
 | ||
| static int load_elf_2_mem(app_struct * app)
 | ||
| {
 | ||
| 	
 | ||
| 	if(app==0) return -1;
 | ||
| 	
 | ||
| 	Elf32_Phdr *phdr_head = NULL;
 | ||
| 	Elf32_Ehdr *Elf_header = NULL;
 | ||
| 	FILE *file1 = app->file;
 | ||
| 	uint32_t rb;
 | ||
| 	
 | ||
|  
 | ||
| 	Elf_header = (Elf32_Ehdr *)malloc(sizeof(Elf32_Ehdr));
 | ||
| 	memset(Elf_header,0,sizeof(Elf32_Ehdr));
 | ||
|  
 | ||
| 	fseek(file1,0,SEEK_SET);
 | ||
| 	rb = fread(Elf_header, sizeof(Elf32_Ehdr), 1, file1);
 | ||
| 	
 | ||
| 	/* 这里 Elf_header->e_phentsize 应该是== sizeof(Elf32_Phdr)*/
 | ||
| 	phdr_head=malloc(Elf_header->e_phentsize *Elf_header->e_phnum);
 | ||
| 	fseek(file1,Elf_header->e_phoff,SEEK_SET);
 | ||
| 	fread(phdr_head,Elf_header->e_phentsize,Elf_header->e_phnum,file1);
 | ||
| 
 | ||
| 	
 | ||
| 	//Elf_header->e_phnum一般等于1
 | ||
| 	for(int i=0;i< Elf_header->e_phnum; i++)
 | ||
| 	{
 | ||
| 		//是程序节
 | ||
| 		//Keil编译的时候程序分为RO,RW,ZI,3个节,但是从运行时角度看来这3个节合并为一个段了
 | ||
| 		if(phdr_head[i].p_type == PT_LOAD )
 | ||
| 		{	
 | ||
| 			//内存
 | ||
| 			if(app->exe_addr==0) 
 | ||
| 			{
 | ||
| 				app->exe_addr=malloc(phdr_head[i].p_memsz);
 | ||
| 				fseek( file1,phdr_head[i].p_offset,SEEK_SET);
 | ||
| 				if((rb = fread(app->exe_addr,1,phdr_head[i].p_filesz,file1)) != phdr_head[i].p_filesz)
 | ||
| 				{
 | ||
| 					printf("function:%s,line:%d, read p_vaddr err!\r\n",__FUNCTION__,__LINE__);
 | ||
| 					printf("read 返回值%d\r\n",rb);
 | ||
| 					printf("read(file,ProHead->p_vaddr,ProHead->p_filesz) != ProHead->p_filesz %x  p_filesz %d\r\n",\
 | ||
| 						phdr_head[i].p_vaddr,phdr_head[i].p_filesz);
 | ||
| 				}
 | ||
| 				
 | ||
| 				/**多余的空间写0,做BSS段**/
 | ||
| 				if((phdr_head[i].p_filesz) < (phdr_head[i].p_memsz))
 | ||
| 				{
 | ||
| 					memset((uint8_t*)app->exe_addr+phdr_head[i].p_filesz,
 | ||
| 							0,
 | ||
| 							phdr_head[i].p_memsz - phdr_head[i].p_filesz);
 | ||
| 				}
 | ||
| 				
 | ||
| 				//找到入口函数地址
 | ||
| 				app->main=(int (*)(void *))((int)app->exe_addr+Elf_header->e_entry);
 | ||
| 				
 | ||
| 				//程序描述信息地址
 | ||
| 				app->app_info=(app_info_struct *)app->exe_addr;
 | ||
| 				
 | ||
| 				printf("%s:exe_addr=0X%08X,size=%d\r\n",__func__,(uint32_t)app->exe_addr,phdr_head[i].p_memsz);
 | ||
| 				printf("%s:main()=0X%08X\r\n",__func__,(uint32_t)app->main);
 | ||
| 				printf("%s:name=%s\r\n",__func__,app->app_info->name);
 | ||
| 				
 | ||
| 				break;
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		
 | ||
| 	}
 | ||
| 	
 | ||
| 	
 | ||
| 	//这里求得RW区在程序映像中的偏移
 | ||
| 	Elf32_Shdr *sher_head=NULL;
 | ||
| 	sher_head=malloc(Elf_header->e_shentsize *Elf_header->e_shnum);
 | ||
| 	fseek(file1,Elf_header->e_shoff,SEEK_SET);
 | ||
| 	fread(sher_head,Elf_header->e_shentsize,Elf_header->e_shnum,file1);
 | ||
| 	
 | ||
| 	for(int i=0;i<Elf_header->e_shnum;i++)
 | ||
| 	{
 | ||
| 		if((sher_head[i].sh_type==SHT_PROGBITS)&&(sher_head[i].sh_flags==(SHF_ALLOC|SHF_EXECINSTR)))
 | ||
| 		{
 | ||
| 			app->ro_size=sher_head[i].sh_size;
 | ||
| 			break;
 | ||
| 		}
 | ||
| 	}
 | ||
| 	free(sher_head);
 | ||
| 	
 | ||
| 	
 | ||
| 	free(Elf_header);
 | ||
| 	free(phdr_head);
 | ||
| 	
 | ||
| 	
 | ||
| 	return 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| //关闭app文件
 | ||
| static void app_close(app_struct *app)
 | ||
| {
 | ||
| 	if(app==0) return;
 | ||
| 	if(app->file) fclose(app->file);
 | ||
| }
 | ||
| 
 | ||
| //打开app文件
 | ||
| static int app_open(app_struct *app,char *path)
 | ||
| {
 | ||
| 	if(app==0) return -1;
 | ||
| 	app->file=fopen(path,"rb");
 | ||
| 	if(app->file)
 | ||
| 	{
 | ||
| 		return 0;
 | ||
| 	}
 | ||
| 	else
 | ||
| 		return -1;
 | ||
| }
 | ||
|  
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| //从文件中获取app的名称
 | ||
| //name,用于保存文件名的数组,长度必须不小于APP_INFO_NAME_MAXLEN
 | ||
| //返回正数成功,0失败,正数代表程序的类型
 | ||
| int app_get_name_from_file(char *path,char *name)
 | ||
| {
 | ||
| 	
 | ||
| 	if(path==0) return 0;
 | ||
| 	if(name==0) return 0;
 | ||
| 	
 | ||
| 	Elf32_Phdr *phdr_head = NULL;
 | ||
| 	Elf32_Ehdr *Elf_header = NULL;
 | ||
| 	FILE *file1 = fopen(path,"rb");
 | ||
| 	uint32_t rb;
 | ||
| 	if(file1==0) return 0;
 | ||
|  
 | ||
| 	Elf_header = (Elf32_Ehdr *)malloc(sizeof(Elf32_Ehdr));
 | ||
| 	memset(Elf_header,0,sizeof(Elf32_Ehdr));
 | ||
|  
 | ||
| 	fseek(file1,0,SEEK_SET);
 | ||
| 	rb = fread(Elf_header, sizeof(Elf32_Ehdr), 1, file1);
 | ||
| 	
 | ||
| 	/* 这里 Elf_header->e_phentsize 应该是== sizeof(Elf32_Phdr)*/
 | ||
| 	phdr_head=malloc(Elf_header->e_phentsize *Elf_header->e_phnum);
 | ||
| 	fseek(file1,Elf_header->e_phoff,SEEK_SET);
 | ||
| 	fread(phdr_head,Elf_header->e_phentsize,Elf_header->e_phnum,file1);
 | ||
| 
 | ||
| 	
 | ||
| 	//Elf_header->e_phnum一般等于1
 | ||
| 	for(int i=0;i< Elf_header->e_phnum; i++)
 | ||
| 	{
 | ||
| 		//是程序节
 | ||
| 		//Keil编译的时候程序分为RO,RW,ZI,3个节,但是从运行时角度看来这3个节合并为一个段了
 | ||
| 		if(phdr_head[i].p_type == PT_LOAD )
 | ||
| 		{
 | ||
| 			fseek( file1,phdr_head[i].p_offset,SEEK_SET);
 | ||
| 			if((rb = fread(name,1,APP_INFO_NAME_MAXLEN,file1)) == APP_INFO_NAME_MAXLEN)
 | ||
| 			{
 | ||
| 				int app_type=0;
 | ||
| 				fread(&app_type,1,sizeof(int),file1);
 | ||
| 				fclose(file1);
 | ||
| 				free(Elf_header);
 | ||
| 				free(phdr_head);
 | ||
| 				return app_type;
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	
 | ||
| 	fclose(file1);
 | ||
| 	free(Elf_header);
 | ||
| 	free(phdr_head);
 | ||
| 	return 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| //app退出运行 0,成功,非0,失败
 | ||
| int app_exit(app_struct *app)
 | ||
| {
 | ||
| 	if(app==0) return -1;
 | ||
| 	
 | ||
| 	//如果app正在运行,需要先退出app
 | ||
| 	if(app->run_state&&app->exit)
 | ||
| 	{
 | ||
| 		app->exit(0);
 | ||
| 	}
 | ||
| 	if(app->run_state==0)
 | ||
| 	{
 | ||
| 		//在app没有运行时才可以删除
 | ||
| 		if(app->exe_addr) free(app->exe_addr);
 | ||
| 		appm_delete(app);
 | ||
| 		return 0;
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		return -1;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| //获取和保存r9寄存器
 | ||
| void *get_r9(void);
 | ||
| void set_r9(void *r9);
 | ||
| 
 | ||
|  
 | ||
| //抢占式调用app,阻塞调用线程以运行app
 | ||
| static int app_run_seize(app_struct *app)
 | ||
| {
 | ||
| 	int ret=0;
 | ||
| 	
 | ||
| 	
 | ||
| 	app->r9=get_r9();
 | ||
| 	set_r9((void *)((int)app->exe_addr+app->ro_size));
 | ||
| 	if (app->main) app->main(app);
 | ||
| 	set_r9(app->r9);
 | ||
| 	
 | ||
| 	app_exit(app);
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	return ret;
 | ||
| }
 | ||
| 
 | ||
| //调用app,保留app镜像
 | ||
| static int app_run_hold(app_struct *app)
 | ||
| {
 | ||
| 	int ret=0;
 | ||
| 	if(app==0) return -1;
 | ||
| 	
 | ||
| 	app->r9=get_r9();
 | ||
| 	set_r9((void *)((int)app->exe_addr+app->ro_size));
 | ||
| 	if (app->main) app->main(app);
 | ||
| 	set_r9(app->r9);
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	return ret;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| static void run_thread_entry(void *t)
 | ||
| {
 | ||
| 	app_struct *app=t;
 | ||
| 	int ret=0;
 | ||
| 	
 | ||
| 		
 | ||
| 	app->r9=get_r9();
 | ||
| 	set_r9((void *)((int)app->exe_addr+app->ro_size));
 | ||
| 	if (app->main) app->main(app);
 | ||
| 	set_r9(app->r9);
 | ||
| 		
 | ||
| 	app_exit(app);
 | ||
| 	
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| //创建新线程以运行app
 | ||
| static int app_run_thread(app_struct *app)
 | ||
| {
 | ||
| 	int ret=0;
 | ||
| 	
 | ||
| 	
 | ||
| 	rt_thread_t rt=rt_thread_create(app->app_info->name,run_thread_entry,app,
 | ||
| 			app->app_info->stack_size,app->app_info->priority,20);
 | ||
| 	rt_thread_startup(rt);
 | ||
| 	ret=0;
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	return ret;
 | ||
| }
 | ||
| 
 | ||
| //运行app
 | ||
| int app_run(app_struct *app)
 | ||
| {
 | ||
| 	int ret=0;
 | ||
| 	if(app->app_info->exe_type==APP_TYPE_SEIZE)
 | ||
| 	{
 | ||
| 		ret=app_run_seize(app);
 | ||
| 	}
 | ||
| 	else if(app->app_info->exe_type==APP_TYPE_THREAD)
 | ||
| 	{
 | ||
| 		ret=app_run_thread(app);
 | ||
| 	}
 | ||
| 	else if(app->app_info->exe_type==APP_TYPE_HOLD)
 | ||
| 	{
 | ||
| 		ret=app_run_hold(app);
 | ||
| 	}
 | ||
| 	return ret;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| int app_run_path(char *path)
 | ||
| {
 | ||
| 	int ret=0;
 | ||
| 	
 | ||
| 	//如果程序已经存在于内存中,则直接调用
 | ||
| 	char name[APP_INFO_NAME_MAXLEN]={0};
 | ||
| 	if(app_get_name_from_file(path,name)!=0)
 | ||
| 	{
 | ||
| 		app_struct *app=appm_find(name);
 | ||
| 		if(app)
 | ||
| 		{
 | ||
| 			if(app->app_info->exe_type==APP_TYPE_HOLD)
 | ||
| 			{
 | ||
| 				ret=app_run_hold(app);
 | ||
| 			}
 | ||
| 			return ret;
 | ||
| 		}
 | ||
| 	}
 | ||
| 	
 | ||
| 	app_struct *app=appm_new();
 | ||
| 	
 | ||
| 	if((app_open(app,path)==0)&&(check_elf_head(app)==0)&&(load_elf_2_mem(app)==0))
 | ||
| 	{
 | ||
| 		app_close(app);
 | ||
| 		app_run(app);
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		appm_delete(app);
 | ||
| 		ret=-1;
 | ||
| 	}
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	
 | ||
| 	return ret;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 |