OSDev.org

The Place to Start for Operating System Developers
It is currently Sat Apr 27, 2024 8:23 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: ELF Loading causes Triple Fault
PostPosted: Sun Mar 03, 2024 8:34 am 
Offline
Member
Member

Joined: Sat Aug 12, 2023 1:48 am
Posts: 40
Location: Nizhny Novgorod, Russia
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:
Code:
#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;
        }
    }
}

Here is the code of ELF:
Code:
section .text
    global _start

_start:
    ret

And, finally, this is the code of page fault handler which causes a page fault (idk why):
Code:
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);
}


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():
Code:
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;
}


Top
 Profile  
 
 Post subject: Re: ELF Loading causes Triple Fault
PostPosted: Sun Mar 03, 2024 5:56 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5146
More information about the page fault would be helpful. What were the values of EIP, CR2, and the error code? Which part of your code does EIP point to? Is CR2 a reasonable address for that code to be accessing?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 21 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group