ELF loader problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

ELF loader problem

Post by nexos »

Hello,
I am currently making an ELF loader for my OS. It parses the program headers, and I know it does it correctly. How every, it #PFs when I launch the program. I know it is a loader problem because a simpler loader I used before worked fine. Here is the code

Code: Select all

VIRTUALADDR SchedElfLoadModule(VIRTUALADDR moduleBase, INT mod, PROCESS* proc)
{
    MULTIBOOT_MODULE* moduleArray = (MULTIBOOT_MODULE*)moduleBase;
    VIRTUALADDR base = (VIRTUALADDR)moduleArray[mod].modStart;
    VIRTUALADDR vbase = (VIRTUALADDR)KePlacementAlloc(0x1000);
    Elf64_Ehdr* hdr = (Elf64_Ehdr*)vbase;
    HalMapAddress((VIRTUALADDR*)HalGetDirectory(), (VIRTUALADDR)hdr, base, PG_PRESENT | PG_WRITEABLE);
    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)
    {
        QWORD offset = hdr->e_phoff;
        for(INT i = 0; i < hdr->e_phnum; i++)
        {
            VIRTUALADDR pbase = vbase + offset;
            Elf64_Phdr* phdr = (Elf64_Phdr*)pbase;
            if(phdr->p_type == PT_LOAD)
            {
                DWORD size = phdr->p_filesz;
                if(!(size & 0xFFFFF000))
                {
                    size &= 0xFFFFF000;
                    size += 0x1000;
                }
                else if(size & 0xFFFFF000)
                {
                    size &= 0xFFFFF000;
                    size += 0x1000;
                }
                for(DWORD i = 0; i < size; i += 0x1000)
                {
                    HalMapAddress((VIRTUALADDR*)proc->pdbr, phdr->p_vaddr + i, base + offset + i, PG_PRESENT | PG_WRITEABLE | PG_USER);
                }
            }
            offset += hdr->e_phentsize;
        }
        return hdr->e_entry;
    }
    return 0;
}
Thanks for your help,
nexos
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: ELF loader problem

Post by nexos »

Never mind, I found the problem. It is pretty obvious :shock: .
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
nullplan
Member
Member
Posts: 1916
Joined: Wed Aug 30, 2017 8:24 am

Re: ELF loader problem

Post by nullplan »

p_vaddr also doesn't have to be page aligned. p_filesz might be less than p_memsz. And what is up with the innermost "if"? If you just want to align "size" to the next page size, you can do:

Code: Select all

size = (size + pagesize - 1) & -pagesize;
//or, in concrete terms:
size = (size + 0xFFF) & -0xFFF;
If the size happens to be page aligned already, then adding 4095 will not change the upper 20 bytes. And if size is even one byte above a page size limit, then adding 4095 will carry over into the upper part.

Also, p_filesz and p_memsz are 64-bits. Although I do agree that having a single segment be longer than 4GB is pretty unlikely.
Carpe diem!
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: ELF loader problem

Post by nexos »

Thanks for your suggestion nullplan!
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Post Reply