Page 1 of 1

Issue with Program Loading

Posted: Wed Mar 18, 2020 6:59 pm
by nexos
Hello,

I am currently making an operating system called NexOS, and am working a program loader that can load PE programs made by MinGW for Linux. It has an Image Base of 4MB. When i execute it, it page faults. Here is the program loading code:

Code: Select all

int entryPoint;
int stack;
extern void execute_internal();

int create_process(char* path)
{
    IMAGE_DOS_HEADER* dosHeader;
    IMAGE_NT_HEADERS* peHeader;
    int size;
    process* proc;
    pdirectory* addressSpace;

    void* buffer = read_file(path, &size);
    dosHeader =(IMAGE_DOS_HEADER*)buffer;
    if(dosHeader->e_magic != 0x5A4D)
    {
        return -1;
    }

    peHeader = (dosHeader->e_lfanew + (uint32_t)buffer);
    addressSpace = get_directory();
    proc = kernel_heap_alloc(sizeof(process));
    proc->addressSpace = addressSpace;
    proc->threads = kernel_heap_alloc(sizeof(thread) * 10);
    proc->threads[0].state.eip = peHeader->OptionalHeader.ImageBase + peHeader->OptionalHeader.AddressOfEntryPoint;
    proc->threads[0].state.eflags = 0x200;
    if(!(size & 0xFFFFF000))
    {
        size &= 0xFFFFF000;
        size += 0x1000;
    }
    for(int i = 0; i < size; i += 4096)
    {
        void* block = alloc_block();
        map_address(addressSpace, peHeader->OptionalHeader.ImageBase + i, (uint32_t)block, I86_PTE_PRESENT | I86_PTE_WRITABLE | I86_PTE_USER);
        memcpy(peHeader->OptionalHeader.ImageBase + i, buffer, 4096);
        buffer += 4096;
    }

    void* stackVirt = peHeader->OptionalHeader.ImageBase + peHeader->OptionalHeader.SizeOfImage + 4096;
    void* stackPhys = alloc_block();
    map_address(addressSpace, (uint32_t)stackVirt, (uint32_t)stackPhys, I86_PTE_PRESENT | I86_PTE_WRITABLE | I86_PTE_USER);
    proc->threads[0].stack = stackVirt;
    proc->threads[0].state.esp = (uint32_t)stackVirt;
    proc->threads[0].state.ebp = (uint32_t)stackVirt;

    entryPoint = proc->threads[0].state.eip;
    stack = proc->threads[0].state.esp;

    execute_internal();

    return 0;
}
The execute_internal function looks like this:

Code: Select all

extern entryPoint
extern stack

global execute_internal

execute_internal:
    cli
    mov ax, 0x23
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    push 0x23
    mov eax, [stack]
    push eax
    push 0x200
    push 0x1b
    mov eax, [entryPoint]
    push eax
    iretd
The full source repo is at https://github.com/NexSuite/NexOS

Re: Issue with Program Loading

Posted: Wed Mar 18, 2020 11:03 pm
by Gigasoft
The initial stack pointer points to the beginning of the stack instead of the end.

Re: Issue with Program Loading

Posted: Thu Mar 19, 2020 12:16 pm
by nexos
I changed that and it still page faults. The value in CR2 is 0x401000.

Re: Issue with Program Loading

Posted: Fri Mar 20, 2020 12:51 am
by Octocontrabass

Code: Select all

    if(!(size & 0xFFFFF000))
    {
        size &= 0xFFFFF000;
        size += 0x1000;
    }
That doesn't look right.

Re: Issue with Program Loading

Posted: Fri Mar 20, 2020 10:41 am
by eekee
@Octocontrabass: That's rounding up to the next 4KiB boundary.

Re: Issue with Program Loading

Posted: Fri Mar 20, 2020 10:44 am
by nexos
I changed it up a little. It now looks like:

Code: Select all

int entryPoint;
int stack;
extern void execute_internal();

int create_process(char* path)
{
    IMAGE_DOS_HEADER* dosHeader;
    IMAGE_NT_HEADERS* peHeader;
    int size;
    process* proc;
    pdirectory* addressSpace;

    void* buffer = read_file(path, &size);
    dosHeader =(IMAGE_DOS_HEADER*)buffer;
    if(dosHeader->e_magic != 0x5A4D)
    {
        return -1;
    }

    peHeader = (dosHeader->e_lfanew + (uint32_t)buffer);
    addressSpace = get_directory();
    proc = kernel_heap_alloc(sizeof(process));
    proc->addressSpace = addressSpace;
    proc->threads = kernel_heap_alloc(sizeof(thread)* 10);
    proc->threads[0].state.eip = peHeader->OptionalHeader.ImageBase + peHeader->OptionalHeader.AddressOfEntryPoint;
    proc->threads[0].state.eflags = 0x200;
    for(int i = 0; i < size; i += 4096)
    {
        void* block = alloc_block();
        map_address(addressSpace, peHeader->OptionalHeader.ImageBase + i, (uint32_t)block, I86_PTE_PRESENT | I86_PTE_WRITABLE | I86_PTE_USER);
        memcpy(peHeader->OptionalHeader.ImageBase + i, buffer, 4096);
        buffer += 4096;
    }

    void* stackVirt = peHeader->OptionalHeader.ImageBase + peHeader->OptionalHeader.SizeOfImage;
    void* stackPhys = alloc_block();
    map_address(addressSpace, (uint32_t)stackVirt, (uint32_t)stackPhys, I86_PTE_PRESENT | I86_PTE_WRITABLE | I86_PTE_USER);
    proc->threads[0].stack = stackVirt;
    proc->threads[0].state.esp = (uint32_t)stackVirt;
    asm("cli");
    switch_pdirectory(addressSpace);
    entryPoint = proc->threads[0].state.eip;
    stack = proc->threads[0].state.esp;
    void (*entry) () = (entryPoint);
    execute_internal();
    return 0;
}
and execute_internal is:

Code: Select all

extern entryPoint
extern stack

global execute_internal

execute_internal:
    mov ax, 0x23
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    push 0x23
    lea eax, [stack]
    push eax
    push 0x200
    push 0x1b
    lea eax, [entryPoint]
    push eax
    iretd
I also tried compiling it under Visual Studio,
and yet it still page faults at address 0x-3FEF7754

Re: Issue with Program Loading

Posted: Sat Mar 21, 2020 12:36 am
by Octocontrabass
eekee wrote:That's rounding up to the next 4KiB boundary.
Maybe that's what it's supposed to do, but that's not what it does.

Re: Issue with Program Loading

Posted: Sat Mar 21, 2020 2:30 am
by iansjack
Is

Code: Select all

0x12345678 & 0xfffff000
true or false?

Re: Issue with Program Loading

Posted: Sat Mar 21, 2020 4:47 am
by eekee
Oh of course! If it's meant to round up, the condition is wrong. Hmm...

Code: Select all

if(size & 0xFFFF)

Re: Issue with Program Loading

Posted: Sat Mar 21, 2020 4:50 am
by iansjack
Still not quite correct. What if size was 0x12345000?

This is where using a debugger is such a useful tool. You would have spotted the problem there as soon as you stepped through the relevant code. That's why I risk boring people (and upsetting some) who ask the community to debug their code by suggesting they learn how to use a debugger. Effort spent up front, with simple user programs, learning how to use gdb, or the like, effectively is the best investment you can make.

Re: Issue with Program Loading

Posted: Sat Mar 21, 2020 5:01 am
by eekee
derp...

Knew I shouldn't have posted. I not has a brain today.

Re: Issue with Program Loading

Posted: Sat Mar 21, 2020 2:34 pm
by nexos
I got it to run in kernel mode, but it won't run in user mode

Re: Issue with Program Loading

Posted: Mon Mar 23, 2020 10:43 am
by Gigasoft
The PDEs must have the User bit set.