OSDev.org
https://forum.osdev.org/

ELF Loading causes Triple Fault
https://forum.osdev.org/viewtopic.php?f=1&t=57139
Page 1 of 1

Author:  KrotovOSdev [ Sun Mar 03, 2024 8:34 am ]
Post subject:  ELF Loading causes Triple Fault

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;
}

Author:  Octocontrabass [ Sun Mar 03, 2024 5:56 pm ]
Post subject:  Re: ELF Loading causes Triple Fault

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?

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/