#include /** * hello.c */ #include #include #include #include #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.usedexe_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;iapp_info->name,name)==0) { return ptr; } } return 0; } app_struct *appm_get(int index) { if(index>=0&&indexrun_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;ie_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; }