ELF Loading causes Triple Fault
Posted: Sun Mar 03, 2024 8:34 am
Hello!
I'm trying to load my first ELF as a GRUB module. I don't know why, but loading procedure throwing page fault, although I mapped all pages which contain my ELF.
So here is the code of my ELF loader:
Here is the code of ELF:
And, finally, this is the code of page fault handler which causes a page fault (idk why):
I'm totally sure that map_page works fine because I've already used it in the kernel. But if it's needed, here is the code of map_page():
I'm trying to load my first ELF as a GRUB module. I don't know why, but loading procedure throwing page fault, although I mapped all pages which contain my ELF.
So here is the code of my ELF loader:
Code: Select all
#include <stdint.h>
#include <stdbool.h>
#include <elf.h>
#include "../include/vmm.h"
#include "../include/pmm.h"
bool vefify_file(Elf32_Ehdr* hdr) {
//map_page((uint32_t)hdr & ~(4095), (uint32_t)hdr & ~(4095), 0, page_directory);
printf("%d\n", (uint32_t)hdr);
printf("ox%x", vmem_translate(&(hdr), page_directory));
/*while (1)
{
}
*/
if (!hdr) return false;
if (hdr->e_ident[EI_MAG0] != ELFMAG0 || hdr->e_ident[EI_MAG1] != ELFMAG1 || hdr->e_ident[EI_MAG2] != ELFMAG2 || hdr->e_ident[EI_MAG3] != ELFMAG3) return false;
if (hdr->e_machine != EM_386 || hdr->e_machine != EM_X86_64) return false;
if (hdr->e_ident[EI_DATA] != ELFDATA2LSB) return false;
if (hdr->e_type != ET_EXEC && hdr->e_type != ET_EXEC) return false;
if (hdr->e_ident[EI_CLASS] != ELFCLASS32) return false;
/*while (1)
{
}*/
return false;
}
uint32_t get_entry_point(uint64_t kvaddr) {
Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*)(uint32_t)kvaddr;
if (!vefify_file(elf_hdr)) return 0;
return elf_hdr->e_entry;
}
bool load_elf(uint64_t kvaddr, pd_entry_t* p_vas, bool user) {
Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*)(uint32_t)kvaddr;
printf("%d\n", kvaddr);
if (!vefify_file((Elf32_Ehdr*)kvaddr)) return 1;
for (uint16_t i = 0; i < elf_hdr->e_phnum; i++) {
Elf32_Phdr* phdr = (Elf32_Phdr*)(elf_hdr->e_phoff + i);
switch (phdr->p_type)
{
case 1:
//load
for (uint32_t j = phdr->p_vaddr; j < phdr->p_filesz; i += 4096) {
uint32_t phys_page = (uint32_t)page_alloc(PAGE_SIZE);
map_page(phys_page, j, user, p_vas);
uint32_t kvirtpage = find_free_vpage(page_directory);
map_page(phys_page, kvirtpage, 0, page_directory);
kmemcpy((void*)((uint32_t)kvaddr + phdr->p_offset + j - phdr->p_vaddr), (void*)kvirtpage, (phdr->p_vaddr + phdr->p_filesz - j > 4096) ? 4096 : phdr->p_vaddr + phdr->p_filesz - j);
unmap_page(kvirtpage, page_directory);
}
break;
default:
break;
}
}
}
Code: Select all
section .text
global _start
_start:
ret
Code: Select all
void do_page_fault(exception_frame* context) {
//TODO: add process page fault handler
uint32_t fault_addr;
asm volatile ("mov %%cr2, %0" : "=r" (fault_addr));
uint16_t pd_index = (fault_addr >> 22) & 0x3FF;
uint16_t pt_index = (fault_addr >> 12) & 0x3FF;
if (!*((pmem_bitmap + (vmem_translate(fault_addr, page_directory) / PAGE_SIZE))) && context->error_code >> 1 & 0x1) {
do_exception(context);
}
if (context->error_code & 0x1) {
do_exception(context);
}
if (fault_addr > 0xFFFFFFFF) {
do_exception(context);
}
map_page(fault_addr & ~(4095), fault_addr & ~(4095), (context->error_code >> 2) & 1, page_directory);
}
Code: Select all
void map_page(uint64_t phys_addr, uint64_t virt_addr, bool user, pd_entry_t* pd) {
uint16_t pd_index = (virt_addr >> 22) & 0x3FF;
uint16_t pt_index = (virt_addr >> 12) & 0x3FF;
if (phys_addr & 0xFFF) {
printf("Cannot map page (virt=%x, phys=%x)\n", virt_addr, phys_addr);
return;
}
pt_entry_t* pt;
if ((pd + pd_index)->frame == 0) {
pt = create_pt();
for (uint16_t i = 0; i < 1024; i++) {
(pt + i)->frame = 0;
}
(pd + pd_index)->frame = (uint32_t)pt >> 12;
}
else pt = (pt_entry_t*)((pd + pd_index)->frame << 12);
(pd + pd_index)->present = 1;
(pd + pd_index)->rw = 1;
(pd + pd_index)->user = user;
(pd + pd_index)->pwt = 1;
(pd + pd_index)->pcd = 0;
(pd + pd_index)->accessed = 0;
(pd + pd_index)->ps = 0;
(pd + pd_index)->unused = 0;
(pd + pd_index)->unused2 = 0;
(pt + pt_index)->present = 1;
(pt + pt_index)->rw = 1;
(pt + pt_index)->user = user;
(pt + pt_index)->pwt = 1;
(pt + pt_index)->pcd = 0;
(pt + pt_index)->accessed = 0;
(pt + pt_index)->pat = 0;
(pt + pt_index)->global = 0;
(pt + pt_index)->unused = 0;
(pt + pt_index)->frame = phys_addr >> 12;
}