🆕 加载elf文件

This commit is contained in:
fslongjin
2022-05-18 18:27:00 +08:00
parent b0a7ec633d
commit 5df5d79900
9 changed files with 277 additions and 50 deletions

View File

@ -10,6 +10,7 @@
#include <filesystem/fat32/fat32.h>
#include <common/stdio.h>
#include <process/spinlock.h>
#include <common/libELF/elf.h>
spinlock_t process_global_pid_write_lock; // 增加pid的写锁
long process_global_pid = 1; // 系统中最大的pid
@ -353,6 +354,126 @@ struct vfs_file_t *process_open_exec_file(char *path)
return filp;
}
/**
* @brief 加载elf格式的程序文件到内存中并设置regs
*
* @param regs 寄存器
* @param path 文件路径
* @return int
*/
static int process_load_elf_file(struct pt_regs *regs, char *path)
{
int retval = 0;
struct vfs_file_t *filp = process_open_exec_file(path);
if ((unsigned long)filp <= 0)
{
kdebug("(unsigned long)filp=%d", (long)filp);
return (unsigned long)filp;
}
void *buf = kmalloc(sizeof(PAGE_4K_SIZE), 0);
uint64_t pos = 0;
pos = filp->file_ops->lseek(filp, 0, SEEK_SET);
retval = filp->file_ops->read(filp, (char *)buf, sizeof(Elf64_Ehdr), &pos);
retval = 0;
if (!elf_check(buf))
{
kerror("Not an ELF file: %s", path);
retval = -ENOTSUP;
goto load_elf_failed;
}
#if ARCH(X86_64)
// 暂时只支持64位的文件
if (((Elf32_Ehdr *)buf)->e_ident[EI_CLASS] != ELFCLASS64)
{
kdebug("((Elf32_Ehdr *)buf)->e_ident[EI_CLASS]=%d", ((Elf32_Ehdr *)buf)->e_ident[EI_CLASS]);
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
Elf64_Ehdr ehdr = *(Elf64_Ehdr *)buf;
// 暂时只支持AMD64架构
if (ehdr.e_machine != EM_AMD64)
{
kerror("e_machine=%d", ehdr.e_machine);
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
#else
#error Unsupported architecture!
#endif
if (ehdr.e_type != ET_EXEC)
{
kdebug("ehdr->e_type=%d", ehdr.e_type);
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
kdebug("e_entry=%#018lx", ehdr.e_entry);
regs->rip = ehdr.e_entry;
current_pcb->mm->code_addr_start = ehdr.e_entry;
// kdebug("ehdr.e_phoff=%#018lx\t ehdr.e_phentsize=%d, ehdr.e_phnum=%d", ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum);
// 将指针移动到program header处
pos = ehdr.e_phoff;
// 读取所有的phdr
pos = filp->file_ops->lseek(filp, pos, SEEK_SET);
filp->file_ops->read(filp, (char *)buf, ehdr.e_phentsize * ehdr.e_phnum, &pos);
if ((unsigned long)filp <= 0)
{
kdebug("(unsigned long)filp=%d", (long)filp);
return (unsigned long)filp;
}
Elf64_Phdr *phdr = buf;
for (int i = 0; i < ehdr.e_phnum; ++i, ++phdr)
{
// kdebug("phdr[%d] phdr->p_offset=%#018lx phdr->p_vaddr=%#018lx phdr->p_memsz=%ld phdr->p_filesz=%ld phdr->p_type=%d", i, phdr->p_offset, phdr->p_vaddr, phdr->p_memsz, phdr->p_filesz, phdr->p_type);
// 不是可加载的段
if (phdr->p_type != PT_LOAD)
continue;
int64_t remain_mem_size = phdr->p_memsz;
int64_t remain_file_size = phdr->p_filesz;
pos = phdr->p_offset;
uint64_t virt_base = phdr->p_vaddr;
while (remain_mem_size > 0)
{
// todo: 改用slab分配4K大小内存块并映射到4K页
if (!mm_check_mapped((uint64_t)current_pcb->mm->pgd, virt_base)) // 未映射,则新增物理页
{
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, virt_base, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
}
pos = filp->file_ops->lseek(filp, pos, SEEK_SET);
int64_t val = 0;
if (remain_file_size != 0)
{
int64_t to_trans = (remain_file_size > PAGE_2M_SIZE) ? PAGE_2M_SIZE : remain_file_size;
val = filp->file_ops->read(filp, (char*)virt_base, to_trans, &pos);
}
if (val < 0)
goto load_elf_failed;
remain_mem_size -= PAGE_2M_SIZE;
remain_file_size -= val;
virt_base += PAGE_2M_SIZE;
}
}
// 分配2MB的栈内存空间
regs->rsp = current_pcb->mm->stack_start;
regs->rbp = current_pcb->mm->stack_start;
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
load_elf_failed:;
if (buf != NULL)
kfree(buf);
return retval;
}
/**
* @brief 使当前进程去执行新的代码
*
@ -398,11 +519,9 @@ ul do_execve(struct pt_regs *regs, char *path)
*
*/
// 映射1个2MB的物理页
unsigned long code_start_addr = 0x800000;
unsigned long stack_start_addr = 0xa00000;
uint64_t brk_start_addr = 0xc00000;
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, code_start_addr, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
unsigned long stack_start_addr = 0x6fffffc00000;
uint64_t brk_start_addr = 0x6fffffc00000;
process_switch_mm(current_pcb);
@ -410,7 +529,6 @@ ul do_execve(struct pt_regs *regs, char *path)
if (!(current_pcb->flags & PF_KTHREAD))
current_pcb->addr_limit = USER_MAX_LINEAR_ADDR;
current_pcb->mm->code_addr_start = code_start_addr;
current_pcb->mm->code_addr_end = 0;
current_pcb->mm->data_addr_start = 0;
current_pcb->mm->data_addr_end = 0;
@ -428,13 +546,7 @@ ul do_execve(struct pt_regs *regs, char *path)
// 清除进程的vfork标志位
current_pcb->flags &= ~PF_VFORK;
struct vfs_file_t *filp = process_open_exec_file(path);
if ((unsigned long)filp <= 0)
return (unsigned long)filp;
memset((void *)code_start_addr, 0, PAGE_2M_SIZE);
uint64_t pos = 0;
int retval = filp->file_ops->read(filp, (char *)code_start_addr, PAGE_2M_SIZE, &pos);
process_load_elf_file(regs, path);
kdebug("execve ok");
return 0;