246 lines
11 KiB
C
246 lines
11 KiB
C
/**********************************************
|
||
* exec.c add by visual 2016.5.23
|
||
*************************************************/
|
||
#include "type.h"
|
||
#include "const.h"
|
||
#include "protect.h"
|
||
#include "string.h"
|
||
#include "proc.h"
|
||
#include "global.h"
|
||
#include "proto.h"
|
||
#include "elf.h"
|
||
#include "fs.h" //added by mingxuan 2019-5-19
|
||
#include "vfs.h"
|
||
#include "stdio.h"
|
||
|
||
static u32 exec_elfcpy(u32 fd, Elf32_Phdr Echo_Phdr, u32 attribute);
|
||
static u32 exec_load(u32 fd, const Elf32_Ehdr *Echo_Ehdr, const Elf32_Phdr Echo_Phdr[]);
|
||
static int exec_pcb_init(char *path);
|
||
|
||
/*======================================================================*
|
||
* sys_exec add by visual 2016.5.23
|
||
*exec系统调用功能实现部分
|
||
*======================================================================*/
|
||
u32 sys_exec(char *path)
|
||
{
|
||
Elf32_Ehdr *Echo_Ehdr = NULL;
|
||
Elf32_Phdr *Echo_Phdr = NULL;
|
||
u32 addr_lin;
|
||
u32 err_temp;
|
||
|
||
char *p_reg; // point to a register in the new kernel stack, added by xw, 17/12/11
|
||
|
||
if (0 == path)
|
||
{
|
||
printf("\x1b[31,47mexec: path ERROR!\x1b[m");
|
||
return -1;
|
||
}
|
||
|
||
/*******************打开文件************************/
|
||
// u32 fd = open(path,"r"); //deleted by mingxuan 2019-5-19
|
||
u32 fd = do_vopen(path, O_RDWR); // deleted by mingxuan 2019-5-19
|
||
|
||
if (fd == -1)
|
||
{
|
||
// printf("sys_exec open error!\n"); //deleted by mingxuan 2019-5-23
|
||
return -1;
|
||
}
|
||
// u32 fd = fake_open(path,"r"); //modified by xw, 18/5/30
|
||
|
||
/*************获取elf信息**************/
|
||
Echo_Ehdr = (Elf32_Ehdr *)K_PHY2LIN(sys_kmalloc(sizeof(Elf32_Ehdr)));
|
||
read_Ehdr(fd, Echo_Ehdr, 0);
|
||
Echo_Phdr = (Elf32_Phdr *)K_PHY2LIN(sys_kmalloc(sizeof(Elf32_Phdr) * Echo_Ehdr->e_phnum));
|
||
for (int i = 0; i < Echo_Ehdr->e_phnum; i++)
|
||
read_Phdr(fd, Echo_Phdr + i, Echo_Ehdr->e_phoff + i * sizeof(Elf32_Phdr));
|
||
|
||
/*************释放进程内存****************/
|
||
// 目前还没有实现 思路是:数据、代码根据text_info和data_info属性决定释放深度,其余内存段可以完全释放
|
||
|
||
/*************根据elf的program复制文件信息**************/
|
||
if (-1 == exec_load(fd, Echo_Ehdr, Echo_Phdr))
|
||
return -1; // 使用了const指针传递
|
||
|
||
/*****************重新初始化该进程的进程表信息(包括LDT)、线性地址布局、进程树属性********************/
|
||
exec_pcb_init(path);
|
||
|
||
/***********************代码、数据、堆、栈***************************/
|
||
// 代码、数据已经处理,将eip重置即可
|
||
p_proc_current->task.regs.eip = Echo_Ehdr->e_entry; // 进程入口线性地址
|
||
p_reg = (char *)(p_proc_current + 1); // added by xw, 17/12/11
|
||
*((u32 *)(p_reg + EIPREG - P_STACKTOP)) = p_proc_current->task.regs.eip; // added by xw, 17/12/11
|
||
|
||
// 栈
|
||
p_proc_current->task.regs.esp = (u32)p_proc_current->task.memmap.stack_lin_base; // 栈地址最高处
|
||
*((u32 *)(p_reg + ESPREG - P_STACKTOP)) = p_proc_current->task.regs.esp; // added by xw, 17/12/11
|
||
|
||
for (addr_lin = p_proc_current->task.memmap.stack_lin_base; addr_lin > p_proc_current->task.memmap.stack_lin_limit; addr_lin -= num_4K)
|
||
{
|
||
err_temp = lin_mapping_phy(addr_lin, // 线性地址 //add by visual 2016.5.9
|
||
MAX_UNSIGNED_INT, // 物理地址 //edit by visual 2016.5.19
|
||
p_proc_current->task.pid, // 进程pid //edit by visual 2016.5.19
|
||
PG_P | PG_USU | PG_RWW, // 页目录的属性位
|
||
PG_P | PG_USU | PG_RWW); // 页表的属性位
|
||
|
||
if (err_temp != 0)
|
||
{
|
||
|
||
kprintf("\x1b[31;47mkernel_main Error:lin_mapping_phy\x1b[m");
|
||
return -1;
|
||
}
|
||
}
|
||
// 堆 用户还没有申请,所以没有分配,只在PCB表里标示了线性起始位置
|
||
|
||
real_close(fd); // added by mingxuan 2019-5-23
|
||
if (Echo_Ehdr != NULL)
|
||
sys_free(Echo_Ehdr);
|
||
if (Echo_Phdr != NULL)
|
||
sys_free(Echo_Phdr);
|
||
|
||
// kprintf("\n\x1b[32;47m[exec success:");//灰底绿字
|
||
// kprintf(path);//灰底绿字
|
||
// kpritff("]\x1b[m");//灰底绿字
|
||
return 0;
|
||
}
|
||
|
||
/*======================================================================*
|
||
* exec_elfcpy add by visual 2016.5.23
|
||
*复制elf中program到内存中
|
||
*======================================================================*/
|
||
static u32 exec_elfcpy(u32 fd, Elf32_Phdr Echo_Phdr, u32 attribute) // 这部分代码将来要移动到exec.c文件中,包括下面exec()中的一部分
|
||
{
|
||
u32 lin_addr = Echo_Phdr.p_vaddr;
|
||
u32 lin_limit = Echo_Phdr.p_vaddr + Echo_Phdr.p_memsz;
|
||
u32 file_offset = Echo_Phdr.p_offset;
|
||
u32 file_limit = Echo_Phdr.p_offset + Echo_Phdr.p_filesz;
|
||
char ch;
|
||
// u32 pde_addr_phy = get_pde_phy_addr(p_proc_current->task.pid); //页目录物理地址 //delete by visual 2016.5.19
|
||
// u32 addr_phy = do_malloc(Echo_Phdr.p_memsz);//申请物理内存 //delete by visual 2016.5.19
|
||
for (; lin_addr < lin_limit; lin_addr++, file_offset++)
|
||
{
|
||
lin_mapping_phy(lin_addr, MAX_UNSIGNED_INT, p_proc_current->task.pid, PG_P | PG_USU | PG_RWW /*说明*/, attribute); // 说明:PDE属性尽量为读写,因为它要映射1024个物理页,可能既有数据,又有代码 //edit by visual 2016.5.19
|
||
if (file_offset < file_limit)
|
||
{ // 文件中还有数据,正常拷贝
|
||
// modified by xw, 18/5/30
|
||
// seek(file_offset);
|
||
// read(fd,&ch,1);
|
||
|
||
// fake_seek(file_offset); //deleted by mingxuan 2019-5-22
|
||
// real_lseek(fd, file_offset, SEEK_SET); //modified by mingxuan 2019-5-22
|
||
do_vlseek(fd, file_offset, SEEK_SET); // modified by mingxuan 2019-5-24
|
||
|
||
// fake_read(fd,&ch,1); //deleted by mingxuan 2019-5-22
|
||
// real_read(fd, &ch, 1); //modified by mingxuan 2019-5-22
|
||
do_vread(fd, &ch, 1); // modified by mingxuan 2019-5-24
|
||
//~xw
|
||
|
||
*((u8 *)lin_addr) = ch; // memcpy((void*)lin_addr,&ch,1);
|
||
}
|
||
else
|
||
{
|
||
// 已初始化数据段拷贝完毕,剩下的是未初始化的数据段,在内存中填0
|
||
*((u8 *)lin_addr) = 0; // memset((void*)lin_addr,0,1);
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*======================================================================*
|
||
* exec_load add by visual 2016.5.23
|
||
*根据elf的program复制文件信息
|
||
*======================================================================*/
|
||
static u32 exec_load(u32 fd, const Elf32_Ehdr *Echo_Ehdr, const Elf32_Phdr Echo_Phdr[])
|
||
{
|
||
u32 ph_num;
|
||
|
||
if (0 == Echo_Ehdr->e_phnum)
|
||
{
|
||
kprintf("\x1b[31;47mexec_load: elf ERROR!\x1b[m", 0x74);
|
||
return -1;
|
||
}
|
||
|
||
// 我们还不能确定elf中一共能有几个program,但就目前我们查看过的elf文件中,只出现过两中program,一种.text(R-E)和一种.data(RW-)
|
||
for (ph_num = 0; ph_num < Echo_Ehdr->e_phnum; ph_num++)
|
||
{
|
||
if (0 == Echo_Phdr[ph_num].p_memsz)
|
||
{ // 最后一个program
|
||
break;
|
||
}
|
||
if (Echo_Phdr[ph_num].p_flags == 0x5) // 101,R_E
|
||
{ // Code Segment
|
||
exec_elfcpy(fd, Echo_Phdr[ph_num], PG_P | PG_USU | PG_RWR); // 进程代码段
|
||
// kprintf("text lin base: 0x%08x\n", Echo_Phdr[ph_num].p_vaddr);
|
||
p_proc_current->task.memmap.text_lin_base = Echo_Phdr[ph_num].p_vaddr;
|
||
p_proc_current->task.memmap.text_lin_limit = Echo_Phdr[ph_num].p_vaddr + Echo_Phdr[ph_num].p_memsz;
|
||
}
|
||
else if (Echo_Phdr[ph_num].p_flags == 0x4) // 110,R__
|
||
{ // It is virtually ROData Segment, god knows what those senpai think about this
|
||
exec_elfcpy(fd, Echo_Phdr[ph_num], PG_P | PG_USU | PG_RWW); // 进程数据段
|
||
// kprintf("data lin base: 0x%08x\n", Echo_Phdr[ph_num].p_vaddr);
|
||
p_proc_current->task.memmap.data_lin_base = Echo_Phdr[ph_num].p_vaddr;
|
||
p_proc_current->task.memmap.data_lin_limit = Echo_Phdr[ph_num].p_vaddr + Echo_Phdr[ph_num].p_memsz;
|
||
}
|
||
else
|
||
{
|
||
kprintf("\x1b[31;47mexec_load: unKnown elf'program!\x1b[m");
|
||
return -1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*======================================================================*
|
||
* exec_init add by visual 2016.5.23
|
||
* 重新初始化寄存器和特权级、线性地址布局
|
||
*======================================================================*/
|
||
static int exec_pcb_init(char *path)
|
||
{
|
||
char *p_regs; // point to registers in the new kernel stack, added by xw, 17/12/11
|
||
|
||
// 名称 状态 特权级 寄存器
|
||
strncpy(p_proc_current->task.p_name, path, sizeof(p_proc_current->task.p_name) - 1); // 名称
|
||
p_proc_current->task.stat = READY; // 状态
|
||
p_proc_current->task.ldts[0].attr1 = DA_C | PRIVILEGE_USER << 5; // 特权级修改为用户级
|
||
p_proc_current->task.ldts[1].attr1 = DA_DRW | PRIVILEGE_USER << 5; // 特权级修改为用户级
|
||
p_proc_current->task.regs.cs = ((8 * 0) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_USER;
|
||
p_proc_current->task.regs.ds = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_USER;
|
||
p_proc_current->task.regs.es = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_USER;
|
||
p_proc_current->task.regs.fs = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_USER;
|
||
p_proc_current->task.regs.ss = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_USER;
|
||
p_proc_current->task.regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | RPL_USER;
|
||
p_proc_current->task.regs.eflags = 0x202; /* IF=1,bit2 永远是1 */
|
||
|
||
/***************copy registers data****************************/
|
||
// copy registers data to the bottom of the new kernel stack
|
||
// added by xw, 17/12/11
|
||
p_regs = (char *)(p_proc_current + 1);
|
||
p_regs -= P_STACKTOP;
|
||
memcpy(p_regs, (char *)p_proc_current, 18 * 4);
|
||
|
||
// 进程表线性地址布局部分,text、data已经在前面初始化了
|
||
p_proc_current->task.memmap.vpage_lin_base = VpageLinBase; // 保留内存基址
|
||
p_proc_current->task.memmap.vpage_lin_limit = VpageLinBase; // 保留内存界限
|
||
p_proc_current->task.memmap.heap_lin_base = HeapLinBase; // 堆基址
|
||
p_proc_current->task.memmap.heap_lin_limit = HeapLinBase; // 堆界限
|
||
p_proc_current->task.memmap.stack_child_limit = StackLinLimitMAX; // add by visual 2016.5.27
|
||
p_proc_current->task.memmap.stack_lin_base = StackLinBase; // 栈基址
|
||
p_proc_current->task.memmap.stack_lin_limit = StackLinBase - 0x4000; // 栈界限(使用时注意栈的生长方向)
|
||
p_proc_current->task.memmap.arg_lin_base = ArgLinBase; // 参数内存基址
|
||
p_proc_current->task.memmap.arg_lin_limit = ArgLinBase; // 参数内存界限
|
||
p_proc_current->task.memmap.kernel_lin_base = KernelLinBase; // 内核基址
|
||
p_proc_current->task.memmap.kernel_lin_limit = KernelLinBase + KernelSize; // 内核大小初始化为8M
|
||
|
||
// 进程树属性,只要改两项,其余不用改
|
||
// p_proc_current->task.info.type = TYPE_PROCESS; //当前是进程还是线程
|
||
// p_proc_current->task.info.real_ppid = -1; //亲父进程,创建它的那个进程
|
||
// p_proc_current->task.info.ppid = -1; //当前父进程
|
||
// p_proc_current->task.info.child_p_num = 0; //子进程数量
|
||
// p_proc_current->task.info.child_process[NR_CHILD_MAX];//子进程列表
|
||
// p_proc_current->task.info.child_t_num = 0; //子线程数量
|
||
// p_proc_current->task.info.child_thread[NR_CHILD_MAX];//子线程列表
|
||
p_proc_current->task.info.text_hold = 1; // 是否拥有代码
|
||
p_proc_current->task.info.data_hold = 1; // 是否拥有数据
|
||
|
||
return 0;
|
||
}
|