mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-11 07:19:20 +00:00
Updated kernel (tl;dr: improved filesystem, tasking, loading files, etc..)
This commit is contained in:
162
Execute/Elf/BaseLoad.cpp
Normal file
162
Execute/Elf/BaseLoad.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
#include <exec.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <msexec.h>
|
||||
#include <cwalk.h>
|
||||
#include <elf.h>
|
||||
#include <abi.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
using namespace Tasking;
|
||||
using VirtualFileSystem::File;
|
||||
using VirtualFileSystem::FileStatus;
|
||||
using VirtualFileSystem::NodeFlags;
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, Tasking::TaskCompatibility Compatibility)
|
||||
{
|
||||
/* We get the base name ("app.elf") */
|
||||
const char *BaseName;
|
||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||
TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture;
|
||||
|
||||
shared_ptr<File> ExFile = vfs->Open(Path);
|
||||
|
||||
if (ExFile->Status != FileStatus::OK)
|
||||
{
|
||||
vfs->Close(ExFile);
|
||||
error("Failed to open file: %s", Path);
|
||||
return {};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ExFile->node->Flags != NodeFlags::FILE)
|
||||
{
|
||||
vfs->Close(ExFile);
|
||||
error("Invalid file path: %s", Path);
|
||||
return {};
|
||||
}
|
||||
else if (GetBinaryType(Path) != BinaryType::BinTypeELF)
|
||||
{
|
||||
vfs->Close(ExFile);
|
||||
error("Invalid file type: %s", Path);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
size_t ExFileSize = ExFile->node->Length;
|
||||
|
||||
/* Allocate elf in memory */
|
||||
void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize));
|
||||
/* Copy the file to the allocated memory */
|
||||
memcpy(ElfFile, (void *)ExFile->node->Address, ExFileSize);
|
||||
debug("Image Size: %#lx - %#lx (length: %ld)", ElfFile, (uintptr_t)ElfFile + ExFileSize, ExFileSize);
|
||||
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
||||
|
||||
switch (ELFHeader->e_machine)
|
||||
{
|
||||
case EM_386:
|
||||
Arch = TaskArchitecture::x32;
|
||||
break;
|
||||
case EM_X86_64:
|
||||
Arch = TaskArchitecture::x64;
|
||||
break;
|
||||
case EM_ARM:
|
||||
Arch = TaskArchitecture::ARM32;
|
||||
break;
|
||||
case EM_AARCH64:
|
||||
Arch = TaskArchitecture::ARM64;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: This shouldn't be ignored
|
||||
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
|
||||
{
|
||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
fixme("ELF32 LSB");
|
||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
fixme("ELF32 MSB");
|
||||
else
|
||||
fixme("ELF32 Unknown");
|
||||
}
|
||||
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
||||
{
|
||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
fixme("ELF64 LSB");
|
||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
fixme("ELF64 MSB");
|
||||
else
|
||||
fixme("ELF64 Unknown");
|
||||
}
|
||||
else
|
||||
fixme("Unknown ELF");
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User, ElfFile);
|
||||
Memory::Virtual pV = Memory::Virtual(Process->PageTable);
|
||||
for (size_t i = 0; i < TO_PAGES(ExFileSize); i++)
|
||||
pV.Remap((void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
// for (size_t i = 0; i < TO_PAGES(ElfLazyResolverSize); i++)
|
||||
// pV.Remap((void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
/* We prepare the ELF for execution (allocate memory, etc...) */
|
||||
ELFBaseLoad bl;
|
||||
|
||||
switch (ELFHeader->e_type)
|
||||
{
|
||||
case ET_REL:
|
||||
bl = ELFLoadRel(ElfFile, ExFile.Get(), Process);
|
||||
break;
|
||||
case ET_EXEC:
|
||||
bl = ELFLoadExec(ElfFile, ExFile.Get(), Process);
|
||||
break;
|
||||
case ET_DYN:
|
||||
bl = ELFLoadDyn(ElfFile, ExFile.Get(), Process);
|
||||
break;
|
||||
case ET_CORE:
|
||||
{
|
||||
fixme("ET_CORE not implemented");
|
||||
TaskManager->RevertProcessCreation(Process);
|
||||
vfs->Close(ExFile);
|
||||
return {};
|
||||
}
|
||||
case ET_NONE:
|
||||
default:
|
||||
{
|
||||
error("Unknown ELF Type: %d", ELFHeader->e_type);
|
||||
vfs->Close(ExFile);
|
||||
TaskManager->RevertProcessCreation(Process);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
TCB *Thread = TaskManager->CreateThread(Process,
|
||||
bl.InstructionPointer,
|
||||
argv, envp, bl.auxv,
|
||||
(IPOffset)0 /* ProgramHeader->p_offset */, // I guess I don't need this
|
||||
Arch,
|
||||
Compatibility);
|
||||
|
||||
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
|
||||
{
|
||||
Thread->Memory->Add(p.Address, p.PageCount);
|
||||
bl.TmpMem->DetachAddress(p.Address);
|
||||
}
|
||||
delete bl.TmpMem;
|
||||
|
||||
bl.sd.Process = Process;
|
||||
bl.sd.Thread = Thread;
|
||||
bl.sd.Status = ExStatus::OK;
|
||||
vfs->Close(ExFile);
|
||||
return bl;
|
||||
}
|
||||
}
|
24
Execute/Elf/Dyn.cpp
Normal file
24
Execute/Elf/Dyn.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include <exec.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <msexec.h>
|
||||
#include <cwalk.h>
|
||||
#include <elf.h>
|
||||
#include <abi.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
using namespace Tasking;
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
ELFBaseLoad ELFLoadDyn(void *BaseImage,
|
||||
VirtualFileSystem::File *ExFile,
|
||||
Tasking::PCB *Process)
|
||||
{
|
||||
fixme("Not implemented");
|
||||
return {};
|
||||
}
|
||||
}
|
@ -14,102 +14,62 @@ using namespace Tasking;
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
void ELFLoadExec(void *BaseImage,
|
||||
size_t Length,
|
||||
Elf64_Ehdr *ELFHeader,
|
||||
Memory::Virtual &pva,
|
||||
SpawnData *ret,
|
||||
char *Path,
|
||||
Tasking::PCB *Process,
|
||||
const char **argv,
|
||||
const char **envp,
|
||||
Tasking::TaskArchitecture Arch,
|
||||
Tasking::TaskCompatibility Comp)
|
||||
ELFBaseLoad ELFLoadExec(void *ElfFile,
|
||||
VirtualFileSystem::File *ExFile,
|
||||
Tasking::PCB *Process)
|
||||
{
|
||||
trace("Executable");
|
||||
Elf64_Phdr *ProgramHeader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
|
||||
debug("p_paddr: %#lx | p_vaddr: %#lx | p_filesz: %#lx | p_memsz: %#lx | p_offset: %#lx", ProgramHeader->p_paddr, ProgramHeader->p_vaddr, ProgramHeader->p_filesz, ProgramHeader->p_memsz, ProgramHeader->p_offset);
|
||||
debug("Executable");
|
||||
ELFBaseLoad ELFBase = {};
|
||||
/* This should be deleted inside BaseLoad.cpp */
|
||||
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
|
||||
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
||||
Memory::Virtual pV(Process->PageTable);
|
||||
|
||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
||||
uint64_t ElfAppSize = 0;
|
||||
uintptr_t EntryPoint = ELFHeader->e_entry;
|
||||
|
||||
Elf64_Phdr ItrProgramHeader;
|
||||
Elf64_Phdr ItrPhdr;
|
||||
|
||||
/* Get base address */
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
||||
}
|
||||
debug("BaseAddress %#lx", BaseAddress);
|
||||
|
||||
/* Get size */
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
uintptr_t SegmentEnd;
|
||||
SegmentEnd = ItrProgramHeader.p_vaddr - BaseAddress + ItrProgramHeader.p_memsz;
|
||||
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
||||
}
|
||||
debug("ElfAppSize %ld", ElfAppSize);
|
||||
|
||||
uint8_t *MemoryImage = nullptr;
|
||||
|
||||
// check for TEXTREL
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
if (ItrProgramHeader.p_type == DT_TEXTREL)
|
||||
{
|
||||
warn("TEXTREL ELF is not fully tested yet!");
|
||||
MemoryImage = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(ElfAppSize));
|
||||
memset(MemoryImage, 0, ElfAppSize);
|
||||
for (uint64_t i = 0; i < TO_PAGES(ElfAppSize); i++)
|
||||
{
|
||||
pva.Remap((void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
debug("Mapping: %#lx -> %#lx", (uintptr_t)MemoryImage + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MemoryImage)
|
||||
{
|
||||
debug("Allocating %ld pages for image", TO_PAGES(ElfAppSize));
|
||||
MemoryImage = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(ElfAppSize));
|
||||
memset(MemoryImage, 0, ElfAppSize);
|
||||
for (uint64_t i = 0; i < TO_PAGES(ElfAppSize); i++)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)ProgramHeader->p_vaddr;
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
pva.Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
debug("Mapping: %#lx -> %#lx", (uintptr_t)Address + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
debug("BaseAddress: %#lx | ElfAppSize: %#lx (%ld, %ld KB)", BaseAddress, ElfAppSize, ElfAppSize, TO_KB(ElfAppSize));
|
||||
|
||||
debug("Solving symbols for address: %#llx", (uintptr_t)BaseImage);
|
||||
Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)BaseImage + ELFHeader->e_shoff);
|
||||
Elf64_Shdr *Dynamic = nullptr;
|
||||
Elf64_Shdr *DynamicSymbol = nullptr;
|
||||
/* If required, MemoryImage will be at virtual address. (unless has PIE)
|
||||
*
|
||||
* tl;dr this is where the code is stored. */
|
||||
void *MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, pV, ElfFile, ElfAppSize);
|
||||
|
||||
debug("Solving symbols for address: %#llx", (uintptr_t)ElfFile);
|
||||
Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)ElfFile + ELFHeader->e_shoff);
|
||||
Elf64_Shdr *DynamicString = nullptr;
|
||||
Elf64_Shdr *SymbolTable = nullptr;
|
||||
Elf64_Shdr *StringTable = nullptr;
|
||||
Elf64_Shdr *RelaPlt = nullptr;
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++)
|
||||
{
|
||||
char *DynamicStringTable = (char *)((uintptr_t)BaseImage + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name);
|
||||
char *DynamicStringTable = (char *)((uintptr_t)ElfFile + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name);
|
||||
|
||||
if (strcmp(DynamicStringTable, ".dynamic") == 0)
|
||||
{
|
||||
Dynamic = &ElfSections[i];
|
||||
debug("Found .dynamic");
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".dynsym") == 0)
|
||||
{
|
||||
DynamicSymbol = &ElfSections[i];
|
||||
debug("Found .dynsym");
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".dynstr") == 0)
|
||||
if (strcmp(DynamicStringTable, ".dynstr") == 0)
|
||||
{
|
||||
DynamicString = &ElfSections[i];
|
||||
debug("Found .dynstr");
|
||||
@ -119,76 +79,57 @@ namespace Execute
|
||||
StringTable = &ElfSections[i];
|
||||
debug("Found .strtab");
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".rela.plt") == 0)
|
||||
{
|
||||
RelaPlt = &ElfSections[i];
|
||||
debug("Found .rela.plt");
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".symtab") == 0)
|
||||
{
|
||||
SymbolTable = &ElfSections[i];
|
||||
debug("Found .symtab");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Unknown section: %s", DynamicStringTable);
|
||||
}
|
||||
}
|
||||
|
||||
UNUSED(Dynamic);
|
||||
UNUSED(DynamicSymbol);
|
||||
UNUSED(SymbolTable);
|
||||
UNUSED(RelaPlt);
|
||||
|
||||
char *NeededLibraries[256];
|
||||
uint64_t InitAddress = 0;
|
||||
uint64_t FiniAddress = 0;
|
||||
|
||||
UNUSED(NeededLibraries);
|
||||
UNUSED(InitAddress);
|
||||
UNUSED(FiniAddress);
|
||||
Vector<char *> NeededLibraries;
|
||||
|
||||
if (!DynamicString)
|
||||
DynamicString = StringTable;
|
||||
|
||||
/* Calculate entry point */
|
||||
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff, sizeof(Elf64_Phdr));
|
||||
if (ItrPhdr.p_vaddr == 0)
|
||||
EntryPoint += (uintptr_t)MemoryImage;
|
||||
|
||||
char InterpreterPath[256];
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
uintptr_t MAddr;
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
switch (ItrProgramHeader.p_type)
|
||||
switch (ItrPhdr.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
fixme("PT_NULL");
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
debug("PT_LOAD - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
||||
MAddr = (ItrProgramHeader.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
|
||||
debug("MAddr: %#lx", MAddr);
|
||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
||||
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
|
||||
fixme("Address: %#lx %s%s%s", MAddr,
|
||||
(ItrPhdr.p_flags & PF_R) ? "R" : "",
|
||||
(ItrPhdr.p_flags & PF_W) ? "W" : "",
|
||||
(ItrPhdr.p_flags & PF_X) ? "X" : "");
|
||||
|
||||
memcpy((void *)MAddr, (uint8_t *)BaseImage + ItrProgramHeader.p_offset, ItrProgramHeader.p_filesz);
|
||||
debug("memcpy operation: %#lx to %#lx for length %ld", (uint8_t *)BaseImage + ItrProgramHeader.p_offset, MemoryImage + MAddr, ItrProgramHeader.p_filesz);
|
||||
memcpy((void *)MAddr, (uint8_t *)ElfFile + ItrPhdr.p_offset, ItrPhdr.p_filesz);
|
||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)ElfFile + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
|
||||
break;
|
||||
}
|
||||
case PT_DYNAMIC:
|
||||
{
|
||||
debug("PT_DYNAMIC - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
||||
|
||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)BaseImage + ItrProgramHeader.p_offset);
|
||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
|
||||
|
||||
for (uint64_t i = 0; i < ItrProgramHeader.p_filesz / sizeof(Elf64_Dyn); i++)
|
||||
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
||||
{
|
||||
switch (Dynamic[i].d_tag)
|
||||
{
|
||||
case DT_NULL:
|
||||
debug("DT_NULL");
|
||||
break;
|
||||
case DT_NEEDED:
|
||||
if (Dynamic[i].d_tag == DT_NEEDED)
|
||||
{
|
||||
if (!DynamicString)
|
||||
{
|
||||
@ -196,240 +137,71 @@ namespace Execute
|
||||
break;
|
||||
}
|
||||
|
||||
debug("DT_NEEDED - Name[%ld]: %s", i, (uintptr_t)BaseImage + DynamicString->sh_offset + Dynamic[i].d_un.d_ptr);
|
||||
NeededLibraries[i] = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
char *ReqLib = (char *)kmalloc(256);
|
||||
strcpy(ReqLib, (char *)((uintptr_t)ElfFile + DynamicString->sh_offset + Dynamic[i].d_un.d_ptr));
|
||||
debug("DT_NEEDED - Name[%ld]: %s", i, ReqLib);
|
||||
NeededLibraries.push_back(ReqLib);
|
||||
}
|
||||
case DT_PLTRELSZ:
|
||||
{
|
||||
fixme("DT_PLTRELSZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_PLTGOT:
|
||||
{
|
||||
fixme("DT_PLTGOT - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_HASH:
|
||||
{
|
||||
fixme("DT_HASH - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_STRTAB:
|
||||
{
|
||||
fixme("DT_STRTAB - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_SYMTAB:
|
||||
{
|
||||
fixme("DT_SYMTAB - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_RELA:
|
||||
{
|
||||
fixme("DT_RELA - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_RELASZ:
|
||||
{
|
||||
fixme("DT_RELASZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_RELAENT:
|
||||
{
|
||||
fixme("DT_RELAENT - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_STRSZ:
|
||||
{
|
||||
fixme("DT_STRSZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_SYMENT:
|
||||
{
|
||||
fixme("DT_SYMENT - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_INIT:
|
||||
{
|
||||
debug("DT_INIT - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
InitAddress = Dynamic[i].d_un.d_ptr;
|
||||
break;
|
||||
}
|
||||
case DT_FINI:
|
||||
{
|
||||
debug("DT_FINI - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
FiniAddress = Dynamic[i].d_un.d_ptr;
|
||||
break;
|
||||
}
|
||||
case DT_SONAME:
|
||||
{
|
||||
fixme("DT_SONAME - Name: %s", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_RPATH:
|
||||
{
|
||||
fixme("DT_RPATH - Name: %s", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_SYMBOLIC:
|
||||
{
|
||||
fixme("DT_SYMBOLIC - Name: %s", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_REL:
|
||||
{
|
||||
fixme("DT_REL - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_RELSZ:
|
||||
{
|
||||
fixme("DT_RELSZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_RELENT:
|
||||
{
|
||||
fixme("DT_RELENT - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_PLTREL:
|
||||
{
|
||||
fixme("DT_PLTREL - Type: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_DEBUG:
|
||||
{
|
||||
fixme("DT_DEBUG - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_TEXTREL:
|
||||
{
|
||||
fixme("DT_TEXTREL - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_JMPREL:
|
||||
{
|
||||
fixme("DT_JMPREL - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_BIND_NOW:
|
||||
{
|
||||
fixme("DT_BIND_NOW - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_INIT_ARRAY:
|
||||
{
|
||||
fixme("DT_INIT_ARRAY - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_FINI_ARRAY:
|
||||
{
|
||||
fixme("DT_FINI_ARRAY - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_INIT_ARRAYSZ:
|
||||
{
|
||||
fixme("DT_INIT_ARRAYSZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_FINI_ARRAYSZ:
|
||||
{
|
||||
fixme("DT_FINI_ARRAYSZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_RUNPATH:
|
||||
{
|
||||
fixme("DT_RUNPATH - Name: %s", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_FLAGS:
|
||||
{
|
||||
fixme("DT_FLAGS - Flags: %#lx", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
case DT_PREINIT_ARRAY:
|
||||
{
|
||||
fixme("DT_PREINIT_ARRAY - Address: %#lx", Dynamic[i].d_un.d_ptr);
|
||||
break;
|
||||
}
|
||||
case DT_PREINIT_ARRAYSZ:
|
||||
{
|
||||
fixme("DT_PREINIT_ARRAYSZ - Size: %ld", Dynamic[i].d_un.d_val);
|
||||
break;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
fixme("DT: %ld", Dynamic[i].d_tag);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Dynamic[i].d_tag == DT_NULL)
|
||||
else if (Dynamic[i].d_tag == DT_NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PT_INTERP: // Do I have to do anything here?
|
||||
case PT_INTERP:
|
||||
{
|
||||
debug("PT_INTERP - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
||||
|
||||
char InterpreterPath[256];
|
||||
memcpy((void *)InterpreterPath, (uint8_t *)BaseImage + ItrProgramHeader.p_offset, 256);
|
||||
fixme("Interpreter: %s", InterpreterPath);
|
||||
FileSystem::FILE *InterpreterFile = vfs->Open(InterpreterPath);
|
||||
if (InterpreterFile->Status != FileSystem::FileStatus::OK)
|
||||
{
|
||||
memcpy((void *)InterpreterPath, (uint8_t *)ElfFile + ItrPhdr.p_offset, 256);
|
||||
debug("Interpreter: %s", InterpreterPath);
|
||||
|
||||
shared_ptr<VirtualFileSystem::File> InterpreterFile = vfs->Open(InterpreterPath);
|
||||
if (InterpreterFile->Status != VirtualFileSystem::FileStatus::OK)
|
||||
warn("Failed to open interpreter file: %s", InterpreterPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Load interpreter file
|
||||
fixme("Interpreter file loaded: %s", InterpreterPath);
|
||||
}
|
||||
vfs->Close(InterpreterFile);
|
||||
|
||||
vfs->Close(InterpreterFile);
|
||||
break;
|
||||
}
|
||||
/* ... */
|
||||
case PT_PHDR:
|
||||
{
|
||||
debug("PT_PHDR - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown or unsupported program header type: %d", ItrProgramHeader.p_type);
|
||||
warn("Unknown or unsupported program header type: %d", ItrPhdr.p_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug("Entry Point: %#lx", ELFHeader->e_entry);
|
||||
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, pV, InterpreterPath);
|
||||
|
||||
Vector<AuxiliaryVector> auxv;
|
||||
debug("Entry Point: %#lx", EntryPoint);
|
||||
|
||||
auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)Path}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t) "x86_64"}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)ELFHeader->e_entry}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
|
||||
auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
|
||||
char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true);
|
||||
strcpy(aux_platform, "x86_64");
|
||||
|
||||
TCB *Thread = TaskManager->CreateThread(Process,
|
||||
(IP)ELFHeader->e_entry,
|
||||
argv, envp, auxv,
|
||||
(IPOffset)0 /* ProgramHeader->p_offset */, // I guess I don't need this
|
||||
Arch,
|
||||
Comp);
|
||||
ret->Process = Process;
|
||||
ret->Thread = Thread;
|
||||
ret->Status = ExStatus::OK;
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)vfs->GetPathFromNode(ExFile->node).Get()}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
|
||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
|
||||
|
||||
ELFBase.InstructionPointer = EntryPoint;
|
||||
|
||||
foreach (auto var in NeededLibraries)
|
||||
kfree(var);
|
||||
|
||||
ELFBase.Success = true;
|
||||
return ELFBase;
|
||||
}
|
||||
}
|
||||
|
284
Execute/Elf/Parse.cpp
Normal file
284
Execute/Elf/Parse.cpp
Normal file
@ -0,0 +1,284 @@
|
||||
#include <exec.hpp>
|
||||
|
||||
#include <msexec.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||
|
||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
|
||||
{
|
||||
return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff);
|
||||
}
|
||||
|
||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
|
||||
{
|
||||
return &GetELFSheader(Header)[Index];
|
||||
}
|
||||
|
||||
char *GetELFStringTable(Elf64_Ehdr *Header)
|
||||
{
|
||||
if (Header->e_shstrndx == SHN_UNDEF)
|
||||
return nullptr;
|
||||
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
|
||||
}
|
||||
|
||||
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset)
|
||||
{
|
||||
char *StringTable = GetELFStringTable(Header);
|
||||
if (StringTable == nullptr)
|
||||
return nullptr;
|
||||
return StringTable + Offset;
|
||||
}
|
||||
|
||||
void *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name)
|
||||
{
|
||||
Elf64_Shdr *SymbolTable = nullptr;
|
||||
Elf64_Shdr *StringTable = nullptr;
|
||||
Elf64_Sym *Symbol = nullptr;
|
||||
char *String = nullptr;
|
||||
|
||||
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *shdr = GetELFSection(Header, i);
|
||||
switch (shdr->sh_type)
|
||||
{
|
||||
case SHT_SYMTAB:
|
||||
SymbolTable = shdr;
|
||||
StringTable = GetELFSection(Header, shdr->sh_link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (SymbolTable == nullptr || StringTable == nullptr)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
|
||||
{
|
||||
Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
||||
String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
||||
if (strcmp(String, Name) == 0)
|
||||
return (void *)Symbol->st_value;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index)
|
||||
{
|
||||
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
|
||||
return 0;
|
||||
Elf64_Shdr *SymbolTable = GetELFSection(Header, Table);
|
||||
|
||||
uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
|
||||
if (Index >= STEntries)
|
||||
{
|
||||
error("Symbol index out of range %d-%u.", Table, Index);
|
||||
return 0xdead;
|
||||
}
|
||||
|
||||
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
|
||||
Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index];
|
||||
|
||||
if (Symbol->st_shndx == SHN_UNDEF)
|
||||
{
|
||||
Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link);
|
||||
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
|
||||
|
||||
void *Target = ELFLookupSymbol(Header, Name);
|
||||
if (Target == nullptr)
|
||||
{
|
||||
if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
error("Undefined external symbol \"%s\".", Name);
|
||||
return 0xdead;
|
||||
}
|
||||
}
|
||||
else
|
||||
return (uintptr_t)Target;
|
||||
}
|
||||
else if (Symbol->st_shndx == SHN_ABS)
|
||||
return Symbol->st_value;
|
||||
else
|
||||
{
|
||||
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
|
||||
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
|
||||
}
|
||||
}
|
||||
|
||||
Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag)
|
||||
{
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
||||
|
||||
Elf64_Phdr ItrPhdr;
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
if (ItrPhdr.p_type == PT_DYNAMIC)
|
||||
{
|
||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
|
||||
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
||||
{
|
||||
if (Dynamic[i].d_tag == Tag)
|
||||
{
|
||||
debug("Found dynamic tag %d at %#lx [d_val: %#lx].", Tag, &Dynamic[i], Dynamic[i].d_un.d_val);
|
||||
return &Dynamic[i];
|
||||
}
|
||||
if (Dynamic[i].d_tag == DT_NULL)
|
||||
{
|
||||
debug("Reached end of dynamic tag list for tag %d.", Tag);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("Dynamic tag %d not found.", Tag);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length)
|
||||
{
|
||||
void *MemoryImage = nullptr;
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
||||
|
||||
/* TODO: Not sure what I am supposed to do with this.
|
||||
* It is supposed to detect if it's PIC or not but I
|
||||
* don't know if it's right. */
|
||||
if (ELFGetDynamicTag(ElfFile, DT_TEXTREL))
|
||||
{
|
||||
fixme("Text relocation is not(?) tested yet!");
|
||||
MemoryImage = (uint8_t *)mem->RequestPages(TO_PAGES(Length), true);
|
||||
memset(MemoryImage, 0, Length);
|
||||
return MemoryImage;
|
||||
}
|
||||
|
||||
Elf64_Phdr ItrPhdr;
|
||||
uintptr_t FirstProgramHeaderVirtualAddress = 0x0;
|
||||
|
||||
bool FirstProgramHeader = false;
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
if (ItrPhdr.p_type == PT_LOAD && !FirstProgramHeader)
|
||||
{
|
||||
FirstProgramHeaderVirtualAddress = ItrPhdr.p_vaddr;
|
||||
FirstProgramHeader = true;
|
||||
}
|
||||
|
||||
if (ItrPhdr.p_type == PT_LOAD && ItrPhdr.p_vaddr == 0)
|
||||
{
|
||||
debug("p_vaddr is 0, allocating %ld pages for image", TO_PAGES(Length));
|
||||
MemoryImage = mem->RequestPages(TO_PAGES(Length), true);
|
||||
memset(MemoryImage, 0, Length);
|
||||
return MemoryImage;
|
||||
}
|
||||
}
|
||||
|
||||
debug("Allocating %ld pages for image", TO_PAGES(Length));
|
||||
MemoryImage = mem->RequestPages(TO_PAGES(Length));
|
||||
memset(MemoryImage, 0, Length);
|
||||
|
||||
if (FirstProgramHeaderVirtualAddress != 0)
|
||||
FirstProgramHeaderVirtualAddress &= 0xFFFFFFFFFFFFF000;
|
||||
else
|
||||
FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage;
|
||||
|
||||
for (size_t i = 0; i < TO_PAGES(Length); i++)
|
||||
{
|
||||
pV.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
|
||||
}
|
||||
return MemoryImage;
|
||||
}
|
||||
|
||||
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter)
|
||||
{
|
||||
if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF)
|
||||
{
|
||||
error("Interpreter \"%s\" is not an ELF file.", Interpreter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No need to check if it's valid, the GetBinaryType() call above does that. */
|
||||
shared_ptr<VirtualFileSystem::File> File = vfs->Open(Interpreter);
|
||||
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)File->node->Address;
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *InterpreterType[6] = {
|
||||
"ET_NONE",
|
||||
"ET_REL",
|
||||
"ET_EXEC",
|
||||
"ET_DYN",
|
||||
"ET_CORE",
|
||||
"ET_LOPROC - ET_HIPROC"};
|
||||
Elf64_Half IntType = ELFHeader->e_type;
|
||||
if (IntType > 5)
|
||||
IntType = 5;
|
||||
debug("Interpreter type: %s - %#x", InterpreterType[IntType], ELFHeader->e_type);
|
||||
#endif
|
||||
|
||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
||||
uint64_t ElfAppSize = 0;
|
||||
|
||||
Elf64_Phdr ItrPhdr;
|
||||
|
||||
/* Get base address */
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
||||
}
|
||||
|
||||
/* Get size */
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
uintptr_t SegmentEnd;
|
||||
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
||||
}
|
||||
|
||||
void *MemoryImage = ELFCreateMemoryImage(mem, pV, (void *)File->node->Address, ElfAppSize);
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
|
||||
if (ItrPhdr.p_type == PT_LOAD)
|
||||
{
|
||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
||||
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
|
||||
fixme("Address: %#lx %s%s%s", MAddr,
|
||||
(ItrPhdr.p_flags & PF_R) ? "R" : "",
|
||||
(ItrPhdr.p_flags & PF_W) ? "W" : "",
|
||||
(ItrPhdr.p_flags & PF_X) ? "X" : "");
|
||||
|
||||
memcpy((void *)MAddr, (uint8_t *)File->node->Address + ItrPhdr.p_offset, ItrPhdr.p_filesz);
|
||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)File->node->Address + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
vfs->Close(File);
|
||||
debug("Interpreter entry point: %#lx (%#lx + %#lx)", (uintptr_t)MemoryImage + ELFHeader->e_entry,
|
||||
(uintptr_t)MemoryImage, ELFHeader->e_entry);
|
||||
return (uintptr_t)MemoryImage + ELFHeader->e_entry;
|
||||
}
|
||||
}
|
93
Execute/Elf/Rel.cpp
Normal file
93
Execute/Elf/Rel.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include <exec.hpp>
|
||||
|
||||
#include <msexec.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||
|
||||
ELFBaseLoad ELFLoadRel(void *BaseImage,
|
||||
VirtualFileSystem::File *ExFile,
|
||||
Tasking::PCB *Process)
|
||||
{
|
||||
debug("Relocatable");
|
||||
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
|
||||
warn("Relocatable ELF is not fully supported yet");
|
||||
/* This should be deleted after with kfree */
|
||||
ELFBaseLoad ELFBase = {};
|
||||
/* This should be deleted inside BaseLoad.cpp */
|
||||
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
|
||||
|
||||
Elf64_Shdr *shdr = GetELFSheader(((Elf64_Ehdr *)BaseImage));
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_NOBITS)
|
||||
{
|
||||
if (!Section->sh_size)
|
||||
continue;
|
||||
if (Section->sh_flags & SHF_ALLOC)
|
||||
{
|
||||
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size));
|
||||
memset(Buffer, 0, Section->sh_size);
|
||||
|
||||
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
||||
for (size_t i = 0; i < TO_PAGES(Section->sh_size); i++)
|
||||
pva.Map((void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), (void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
Section->sh_offset = (uintptr_t)Buffer - (uintptr_t)BaseImage;
|
||||
debug("Section %ld", Section->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_REL)
|
||||
{
|
||||
for (size_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
|
||||
{
|
||||
Elf64_Rel *RelTable = &((Elf64_Rel *)((uintptr_t)BaseImage + Section->sh_offset))[Index];
|
||||
Elf64_Shdr *Target = GetELFSection(((Elf64_Ehdr *)BaseImage), Section->sh_info);
|
||||
|
||||
uintptr_t *RelAddress = (uintptr_t *)(((uintptr_t)BaseImage + Target->sh_offset) + RelTable->r_offset);
|
||||
uint64_t SymbolValue = 0;
|
||||
|
||||
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
|
||||
{
|
||||
SymbolValue = ELFGetSymbolValue(((Elf64_Ehdr *)BaseImage), Section->sh_link, ELF64_R_SYM(RelTable->r_info));
|
||||
if (SymbolValue == 0xdead)
|
||||
{
|
||||
delete ELFBase.TmpMem;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
switch (ELF64_R_TYPE(RelTable->r_info))
|
||||
{
|
||||
case R_386_NONE:
|
||||
break;
|
||||
case R_386_32:
|
||||
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
|
||||
break;
|
||||
case R_386_PC32:
|
||||
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uintptr_t)RelAddress);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
|
||||
delete ELFBase.TmpMem;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
debug("Symbol value: %#lx", SymbolValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ELFBase;
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ namespace Execute
|
||||
void StartExecuteService()
|
||||
{
|
||||
mem = new Memory::MemMgr;
|
||||
return;
|
||||
// return;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -53,7 +53,7 @@ namespace Execute
|
||||
}
|
||||
}
|
||||
|
||||
SharedLibraries *AddLibrary(char *Identifier, void *LibraryImage, size_t Length)
|
||||
SharedLibraries *AddLibrary(char *Identifier, void *ElfImage, size_t Length, const Memory::Virtual &pV)
|
||||
{
|
||||
SmartLock(ExecuteServiceLock);
|
||||
SharedLibraries sl;
|
||||
@ -62,12 +62,47 @@ namespace Execute
|
||||
sl.Timeout = TimeManager->CalculateTarget(600000); /* 10 minutes */
|
||||
sl.RefCount = 0;
|
||||
|
||||
void *BaseLibImage = mem->RequestPages(TO_PAGES(Length));
|
||||
memcpy(BaseLibImage, (void *)LibraryImage, Length);
|
||||
sl.Address = BaseLibImage;
|
||||
void *LibFile = mem->RequestPages(TO_PAGES(Length), true);
|
||||
memcpy(LibFile, (void *)ElfImage, Length);
|
||||
|
||||
Memory::Virtual ncpV = pV;
|
||||
sl.MemoryImage = ELFCreateMemoryImage(mem, ncpV, LibFile, Length);
|
||||
|
||||
{
|
||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
||||
Elf64_Phdr ItrProgramHeader;
|
||||
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
if (ItrProgramHeader.p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
||||
uintptr_t MAddr = (ItrProgramHeader.p_vaddr - BaseAddress) + (uintptr_t)sl.MemoryImage;
|
||||
fixme("Address: %#lx %s%s%s", MAddr,
|
||||
(ItrProgramHeader.p_flags & PF_R) ? "R" : "",
|
||||
(ItrProgramHeader.p_flags & PF_W) ? "W" : "",
|
||||
(ItrProgramHeader.p_flags & PF_X) ? "X" : "");
|
||||
|
||||
memcpy((void *)MAddr, (uint8_t *)LibFile + ItrProgramHeader.p_offset, ItrProgramHeader.p_filesz);
|
||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)LibFile + ItrProgramHeader.p_offset, (uintptr_t)MAddr, ItrProgramHeader.p_filesz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sl.Address = LibFile;
|
||||
sl.Length = Length;
|
||||
|
||||
debug("Library %s loaded at %#lx", Identifier, BaseLibImage);
|
||||
debug("Library %s loaded at %#lx (full file: %#lx)", Identifier, sl.MemoryImage, LibFile);
|
||||
|
||||
Libs.push_back(sl);
|
||||
return &Libs[Libs.size() - 1];
|
||||
@ -77,262 +112,4 @@ namespace Execute
|
||||
{
|
||||
SmartLock(ExecuteServiceLock);
|
||||
}
|
||||
|
||||
void AttachLibrary(SharedLibraries *Lib, void *BaseImage)
|
||||
{
|
||||
SmartLock(ExecuteServiceLock);
|
||||
|
||||
BinaryType Type = GetBinaryType(BaseImage);
|
||||
switch (Type)
|
||||
{
|
||||
case BinaryType::BinTypeFex:
|
||||
{
|
||||
fixme("Fex is not supported yet");
|
||||
return;
|
||||
}
|
||||
case BinaryType::BinTypeELF:
|
||||
{
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)BaseImage;
|
||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
||||
size_t ElfAppSize = 0;
|
||||
Elf64_Phdr ItrProgramHeader;
|
||||
|
||||
Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)BaseImage + ELFHeader->e_shoff);
|
||||
Elf64_Shdr *Dynamic = nullptr;
|
||||
Elf64_Shdr *DynamicSymbol = nullptr;
|
||||
Elf64_Shdr *DynamicString = nullptr;
|
||||
Elf64_Shdr *SymbolTable = nullptr;
|
||||
Elf64_Shdr *StringTable = nullptr;
|
||||
Elf64_Shdr *RelaPlt = nullptr;
|
||||
Elf64_Shdr *GotPlt = nullptr;
|
||||
size_t SymbolCount = 0;
|
||||
|
||||
size_t GOTSize = 0;
|
||||
Elf64_Addr *GOTEntry = 0;
|
||||
|
||||
uintptr_t RelaOffset = 0;
|
||||
uint64_t RelaEnt = 0;
|
||||
size_t RelaSize = 0;
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrProgramHeader, (uint8_t *)BaseImage + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
uintptr_t SegmentEnd;
|
||||
SegmentEnd = ItrProgramHeader.p_vaddr - BaseAddress + ItrProgramHeader.p_memsz;
|
||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++)
|
||||
{
|
||||
char *DynamicStringTable = (char *)((uintptr_t)BaseImage + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name);
|
||||
|
||||
if (strcmp(DynamicStringTable, ".dynamic") == 0)
|
||||
{
|
||||
Dynamic = &ElfSections[i];
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".dynsym") == 0)
|
||||
{
|
||||
DynamicSymbol = &ElfSections[i];
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".dynstr") == 0)
|
||||
{
|
||||
DynamicString = &ElfSections[i];
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".strtab") == 0)
|
||||
{
|
||||
StringTable = &ElfSections[i];
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".rela.plt") == 0)
|
||||
{
|
||||
RelaPlt = &ElfSections[i];
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".got.plt") == 0)
|
||||
{
|
||||
GotPlt = &ElfSections[i];
|
||||
}
|
||||
else if (strcmp(DynamicStringTable, ".symtab") == 0)
|
||||
{
|
||||
SymbolTable = &ElfSections[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (ItrProgramHeader.p_type == PT_DYNAMIC)
|
||||
{
|
||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)BaseImage + ItrProgramHeader.p_offset);
|
||||
|
||||
for (uint64_t i = 0; i < ItrProgramHeader.p_filesz / sizeof(Elf64_Dyn); i++)
|
||||
{
|
||||
switch (Dynamic[i].d_tag)
|
||||
{
|
||||
case DT_PLTRELSZ:
|
||||
{
|
||||
GOTSize = Dynamic[i].d_un.d_val;
|
||||
break;
|
||||
}
|
||||
case DT_PLTGOT:
|
||||
{
|
||||
GOTEntry = (Elf64_Addr *)Dynamic[i].d_un.d_ptr;
|
||||
break;
|
||||
}
|
||||
case DT_RELA:
|
||||
{
|
||||
RelaOffset = Dynamic[i].d_un.d_ptr;
|
||||
break;
|
||||
}
|
||||
case DT_RELASZ:
|
||||
{
|
||||
RelaSize = Dynamic[i].d_un.d_val;
|
||||
break;
|
||||
}
|
||||
case DT_RELAENT:
|
||||
{
|
||||
RelaEnt = Dynamic[i].d_un.d_val;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Dynamic[i].d_tag == DT_NULL)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug("BaseAddress: %#lx Size: %ld", BaseAddress, ElfAppSize);
|
||||
|
||||
if (RelaOffset != 0)
|
||||
{
|
||||
if (RelaEnt != sizeof(Elf64_Rela))
|
||||
{
|
||||
error("RelaEnt != sizeof(Elf64_Rela)");
|
||||
/* I should exit here I guess... */
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t RelaOffsetItr = 0; RelaOffsetItr < RelaSize; RelaOffsetItr += RelaEnt)
|
||||
{
|
||||
Elf64_Rela *Rela = (Elf64_Rela *)(((char *)BaseImage) + RelaOffset + RelaOffsetItr);
|
||||
|
||||
switch (Rela->r_info)
|
||||
{
|
||||
case R_X86_64_RELATIVE:
|
||||
{
|
||||
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)BaseImage + Rela->r_offset);
|
||||
*Ptr = (uintptr_t)Lib->Address + Rela->r_addend;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fixme("Rela: %ld", Rela->r_info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
debug("No Rela");
|
||||
|
||||
if (DynamicSymbol != nullptr)
|
||||
SymbolCount = DynamicSymbol->sh_size / sizeof(Elf64_Sym);
|
||||
else if (SymbolTable != nullptr)
|
||||
SymbolCount = SymbolTable->sh_size / sizeof(Elf64_Sym);
|
||||
|
||||
debug("GOT Address %#lx Size %#lx Entry %#lx",
|
||||
GOTEntry, GOTSize, GOTEntry ? GOTEntry : 0);
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpData("Old GOT", (void *)GOTEntry, GOTSize);
|
||||
|
||||
if (DynamicSymbol && DynamicString)
|
||||
for (size_t i = 0; i < SymbolCount; i++)
|
||||
{
|
||||
Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)BaseImage + DynamicSymbol->sh_offset + i * sizeof(Elf64_Sym));
|
||||
char *SymbolName = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Symbol->st_name);
|
||||
if (GOTEntry)
|
||||
if (GOTEntry[i])
|
||||
{
|
||||
uintptr_t SymbolAddress = GOTEntry[i];
|
||||
debug("New GOTEntry[%d] - Symbol %s Address %#lx", i, SymbolName, SymbolAddress);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < GOTSize; i++)
|
||||
if (GOTEntry)
|
||||
if (GOTEntry[i])
|
||||
debug("GOTEntry[%d] = %#lx", i, GOTEntry[i]);
|
||||
#endif
|
||||
|
||||
GOTEntry[1] = (uintptr_t)BaseImage;
|
||||
GOTEntry[2] = (uintptr_t)ElfLazyResolver;
|
||||
|
||||
if (DynamicSymbol && DynamicString && GOTEntry)
|
||||
for (size_t i = 0; i < SymbolCount; i++)
|
||||
{
|
||||
Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)BaseImage + DynamicSymbol->sh_offset + i * sizeof(Elf64_Sym));
|
||||
char *SymbolName = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Symbol->st_name);
|
||||
|
||||
switch (ELF64_ST_TYPE(Symbol->st_info))
|
||||
{
|
||||
case STT_OBJECT:
|
||||
fixme("STT_OBJECT");
|
||||
case STT_FUNC:
|
||||
{
|
||||
uintptr_t SymbolAddress = (uintptr_t)ELFLookupSymbol((Elf64_Ehdr *)Lib->Address, SymbolName);
|
||||
if (SymbolAddress == 0)
|
||||
{
|
||||
error("Symbol %s not found", SymbolName);
|
||||
continue;
|
||||
}
|
||||
GOTEntry[i] = (uintptr_t)Lib->Address + SymbolAddress;
|
||||
debug("%d %#lx Symbol %s at %#lx (%#lx)", i, &GOTEntry[i], SymbolName, SymbolAddress, (uintptr_t)Lib->Address + SymbolAddress);
|
||||
break;
|
||||
}
|
||||
case STT_NOTYPE:
|
||||
break;
|
||||
default:
|
||||
error("Unsupported symbol type %d", ELF64_ST_TYPE(Symbol->st_info));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpData("New GOT", (void *)GOTEntry, GOTSize);
|
||||
|
||||
if (DynamicSymbol && DynamicString)
|
||||
for (size_t i = 0; i < SymbolCount; i++)
|
||||
{
|
||||
Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)BaseImage + DynamicSymbol->sh_offset + i * sizeof(Elf64_Sym));
|
||||
char *SymbolName = (char *)((uintptr_t)BaseImage + DynamicString->sh_offset + Symbol->st_name);
|
||||
if (GOTEntry)
|
||||
if (GOTEntry[i])
|
||||
{
|
||||
uintptr_t SymbolAddress = GOTEntry[i];
|
||||
debug("New GOTEntry[%d] - Symbol %s Address %#lx", i, SymbolName, SymbolAddress);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < GOTSize; i++)
|
||||
if (GOTEntry)
|
||||
if (GOTEntry[i])
|
||||
debug("GOTEntry[%d] = %#lx", i, GOTEntry[i]);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unsupported binary type %d", Type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Lib->RefCount++;
|
||||
debug("Attached library %s", Lib->Identifier);
|
||||
}
|
||||
}
|
||||
|
21
Execute/Fex/BaseLoad.cpp
Normal file
21
Execute/Fex/BaseLoad.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <exec.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <msexec.h>
|
||||
#include <cwalk.h>
|
||||
#include <elf.h>
|
||||
#include <abi.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
using namespace Tasking;
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
void FEXLoad()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -7,227 +7,77 @@
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
BinaryType GetBinaryType(void *Image)
|
||||
{
|
||||
Fex *FexHdr = (Fex *)Image;
|
||||
|
||||
/* Elf64_Ehdr and Elf32_Ehdr are very similar (Elf64_Half and
|
||||
Elf32_Half are the same size type) so we can use directly Elf64_Ehdr. */
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)Image;
|
||||
|
||||
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image;
|
||||
|
||||
/* Check Fex magic */
|
||||
if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0')
|
||||
{
|
||||
/* If the fex type is driver, we shouldn't return as Fex. */
|
||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||
{
|
||||
debug("Image - Fex");
|
||||
return BinaryType::BinTypeFex;
|
||||
}
|
||||
else if (FexHdr->Type == FexFormatType::FexFormatType_Driver)
|
||||
debug("Fex Driver is not supposed to be executed.");
|
||||
}
|
||||
/* Check ELF magic. */
|
||||
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||
{
|
||||
debug("Image - ELF");
|
||||
return BinaryType::BinTypeELF;
|
||||
}
|
||||
/* Every Windows executable starts with MZ header. */
|
||||
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew);
|
||||
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew);
|
||||
|
||||
/* TODO: LE, EDOS */
|
||||
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
debug("Image - PE");
|
||||
return BinaryType::BinTypePE;
|
||||
}
|
||||
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
||||
{
|
||||
debug("Image - NE");
|
||||
return BinaryType::BinTypeNE;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Image - MZ");
|
||||
return BinaryType::BinTypeMZ;
|
||||
}
|
||||
}
|
||||
|
||||
/* ... */
|
||||
return BinaryType::BinTypeUnknown;
|
||||
}
|
||||
|
||||
BinaryType GetBinaryType(char *Path)
|
||||
{
|
||||
BinaryType Type = BinaryType::BinTypeInvalid;
|
||||
FileSystem::FILE *ExFile = vfs->Open(Path);
|
||||
shared_ptr<VirtualFileSystem::File> ExFile = vfs->Open(Path);
|
||||
|
||||
if (ExFile->Status == FileSystem::FileStatus::OK)
|
||||
if (ExFile->Status == VirtualFileSystem::FileStatus::OK)
|
||||
{
|
||||
if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE)
|
||||
{
|
||||
Fex *FexHdr = (Fex *)ExFile->Node->Address;
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ExFile->Node->Address;
|
||||
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)ExFile->Node->Address;
|
||||
if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0')
|
||||
{
|
||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||
{
|
||||
trace("%s - Fex", Path);
|
||||
Type = BinaryType::BinTypeFex;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||
{
|
||||
trace("%s - ELF", Path);
|
||||
Type = BinaryType::BinTypeELF;
|
||||
goto Exit;
|
||||
}
|
||||
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew);
|
||||
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew);
|
||||
if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
||||
{
|
||||
trace("%s - NE", Path);
|
||||
Type = BinaryType::BinTypeNE;
|
||||
}
|
||||
else if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
trace("%s - PE", Path);
|
||||
Type = BinaryType::BinTypePE;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace("%s - MZ", Path);
|
||||
Type = BinaryType::BinTypeMZ;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Type = BinaryType::BinTypeUnknown;
|
||||
}
|
||||
debug("File opened: %s", Path);
|
||||
Type = GetBinaryType((void *)ExFile->node->Address);
|
||||
}
|
||||
Exit:
|
||||
|
||||
vfs->Close(ExFile);
|
||||
return Type;
|
||||
}
|
||||
|
||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||
|
||||
static inline Elf64_Shdr *GetElfSheader(Elf64_Ehdr *Header) { return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff); }
|
||||
static inline Elf64_Shdr *GetElfSection(Elf64_Ehdr *Header, uint64_t Index) { return &GetElfSheader(Header)[Index]; }
|
||||
|
||||
static inline char *GetElfStringTable(Elf64_Ehdr *Header)
|
||||
{
|
||||
if (Header->e_shstrndx == SHN_UNDEF)
|
||||
return nullptr;
|
||||
return (char *)Header + GetElfSection(Header, Header->e_shstrndx)->sh_offset;
|
||||
}
|
||||
|
||||
static inline char *elf_lookup_string(Elf64_Ehdr *Header, uintptr_t Offset)
|
||||
{
|
||||
char *StringTable = GetElfStringTable(Header);
|
||||
if (StringTable == nullptr)
|
||||
return nullptr;
|
||||
return StringTable + Offset;
|
||||
}
|
||||
|
||||
static void *ElfLookupSymbol(Elf64_Ehdr *Header, const char *Name)
|
||||
{
|
||||
Elf64_Shdr *SymbolTable = nullptr;
|
||||
Elf64_Shdr *StringTable = nullptr;
|
||||
Elf64_Sym *Symbol = nullptr;
|
||||
char *String = nullptr;
|
||||
|
||||
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *shdr = GetElfSection(Header, i);
|
||||
switch (shdr->sh_type)
|
||||
{
|
||||
case SHT_SYMTAB:
|
||||
SymbolTable = shdr;
|
||||
StringTable = GetElfSection(Header, shdr->sh_link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (SymbolTable == nullptr || StringTable == nullptr)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
|
||||
{
|
||||
Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
||||
String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
||||
if (strcmp(String, Name) == 0)
|
||||
return (void *)Symbol->st_value;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint32_t Index)
|
||||
{
|
||||
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
|
||||
return 0;
|
||||
Elf64_Shdr *SymbolTable = GetElfSection(Header, Table);
|
||||
|
||||
uint32_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
|
||||
if (Index >= STEntries)
|
||||
{
|
||||
error("Symbol index out of range %d-%u.", Table, Index);
|
||||
return 0xdead;
|
||||
}
|
||||
|
||||
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
|
||||
Elf32_Sym *Symbol = &((Elf32_Sym *)SymbolAddress)[Index];
|
||||
|
||||
if (Symbol->st_shndx == SHN_UNDEF)
|
||||
{
|
||||
Elf64_Shdr *StringTable = GetElfSection(Header, SymbolTable->sh_link);
|
||||
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
|
||||
|
||||
void *Target = ElfLookupSymbol(Header, Name);
|
||||
if (Target == nullptr)
|
||||
{
|
||||
if (ELF32_ST_BIND(Symbol->st_info) & STB_WEAK)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
error("Undefined external symbol \"%s\".", Name);
|
||||
return 0xdead;
|
||||
}
|
||||
}
|
||||
else
|
||||
return (uintptr_t)Target;
|
||||
}
|
||||
else if (Symbol->st_shndx == SHN_ABS)
|
||||
return Symbol->st_value;
|
||||
else
|
||||
{
|
||||
Elf64_Shdr *Target = GetElfSection(Header, Symbol->st_shndx);
|
||||
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void *ELFLoadRel(Elf64_Ehdr *Header)
|
||||
{
|
||||
Elf64_Shdr *shdr = GetElfSheader(Header);
|
||||
for (uint64_t i = 0; i < Header->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_NOBITS)
|
||||
{
|
||||
if (!Section->sh_size)
|
||||
continue;
|
||||
if (Section->sh_flags & SHF_ALLOC)
|
||||
{
|
||||
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size));
|
||||
memset(Buffer, 0, Section->sh_size);
|
||||
|
||||
Memory::Virtual pva = Memory::Virtual(/* TODO TODO TODO TODO TODO TODO */);
|
||||
for (size_t i = 0; i < TO_PAGES(Section->sh_size); i++)
|
||||
pva.Map((void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), (void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
Section->sh_offset = (uint64_t)Buffer - (uint64_t)Header;
|
||||
debug("Section %ld", Section->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < Header->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_REL)
|
||||
{
|
||||
for (size_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
|
||||
{
|
||||
Elf64_Rel *RelTable = &((Elf64_Rel *)((uintptr_t)Header + Section->sh_offset))[Index];
|
||||
Elf64_Shdr *Target = GetElfSection(Header, Section->sh_info);
|
||||
|
||||
uintptr_t *RelAddress = (uintptr_t *)(((uintptr_t)Header + Target->sh_offset) + RelTable->r_offset);
|
||||
uint64_t SymbolValue = 0;
|
||||
|
||||
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
|
||||
{
|
||||
SymbolValue = ELFGetSymbolValue(Header, Section->sh_link, ELF64_R_SYM(RelTable->r_info));
|
||||
if (SymbolValue == 0xdead)
|
||||
return (void *)0xdeadbeef;
|
||||
}
|
||||
|
||||
switch (ELF64_R_TYPE(RelTable->r_info))
|
||||
{
|
||||
case R_386_NONE:
|
||||
break;
|
||||
case R_386_32:
|
||||
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
|
||||
break;
|
||||
case R_386_PC32:
|
||||
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uintptr_t)RelAddress);
|
||||
break;
|
||||
default:
|
||||
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
|
||||
return (void *)0xdeadbeef;
|
||||
}
|
||||
debug("Symbol value: %#lx", SymbolValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (void *)Header->e_entry;
|
||||
}
|
||||
}
|
||||
|
@ -20,175 +20,74 @@ namespace Execute
|
||||
.Process = nullptr,
|
||||
.Thread = nullptr};
|
||||
|
||||
FileSystem::FILE *ExFile = vfs->Open(Path);
|
||||
if (ExFile->Status == FileSystem::FileStatus::OK)
|
||||
shared_ptr<VirtualFileSystem::File> ExFile = vfs->Open(Path);
|
||||
|
||||
if (ExFile->Status == VirtualFileSystem::FileStatus::OK)
|
||||
{
|
||||
if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE)
|
||||
if (ExFile->node->Flags != VirtualFileSystem::NodeFlags::FILE)
|
||||
{
|
||||
BinaryType Type = GetBinaryType(Path);
|
||||
switch (Type)
|
||||
{
|
||||
case BinaryType::BinTypeFex:
|
||||
{
|
||||
#if defined(__amd64__)
|
||||
|
||||
Fex *FexHdr = (Fex *)ExFile->Node->Address;
|
||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||
{
|
||||
const char *BaseName;
|
||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
|
||||
|
||||
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length));
|
||||
memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length);
|
||||
|
||||
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
||||
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
|
||||
pva.Map((void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), (void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
Vector<AuxiliaryVector> auxv; // TODO!
|
||||
|
||||
TCB *Thread = TaskManager->CreateThread(Process,
|
||||
(IP)FexHdr->EntryPoint,
|
||||
argv, envp, auxv,
|
||||
(IPOffset)BaseImage,
|
||||
TaskArchitecture::x64,
|
||||
TaskCompatibility::Native);
|
||||
ret.Process = Process;
|
||||
ret.Thread = Thread;
|
||||
ret.Status = ExStatus::OK;
|
||||
#elif defined(__i386__)
|
||||
if (1)
|
||||
{
|
||||
#elif defined(__aarch64__)
|
||||
if (1)
|
||||
{
|
||||
#endif
|
||||
goto Exit;
|
||||
}
|
||||
ret.Status = ExStatus::InvalidFileHeader;
|
||||
goto Exit;
|
||||
}
|
||||
case BinaryType::BinTypeELF:
|
||||
{
|
||||
#if defined(__amd64__)
|
||||
const char *BaseName;
|
||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||
|
||||
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length));
|
||||
memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length);
|
||||
debug("Image Size: %#lx - %#lx (length: %ld)", BaseImage, (uintptr_t)BaseImage + ExFile->Node->Length, ExFile->Node->Length);
|
||||
|
||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User, BaseImage);
|
||||
|
||||
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
||||
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
|
||||
pva.Remap((void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), (void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)BaseImage;
|
||||
|
||||
TaskArchitecture Arch = TaskArchitecture::x64;
|
||||
TaskCompatibility Comp = TaskCompatibility::Native;
|
||||
if (ELFHeader->e_machine == EM_386)
|
||||
Arch = TaskArchitecture::x32;
|
||||
else if (ELFHeader->e_machine == EM_AMD64)
|
||||
Arch = TaskArchitecture::x64;
|
||||
else if (ELFHeader->e_machine == EM_AARCH64)
|
||||
Arch = TaskArchitecture::ARM64;
|
||||
else
|
||||
Arch = TaskArchitecture::UnknownArchitecture;
|
||||
|
||||
// TODO: Should I care about this?
|
||||
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
|
||||
{
|
||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
fixme("ELF32 LSB");
|
||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
fixme("ELF32 MSB");
|
||||
else
|
||||
fixme("ELF32 Unknown");
|
||||
}
|
||||
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
||||
{
|
||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||
fixme("ELF64 LSB");
|
||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
fixme("ELF64 MSB");
|
||||
else
|
||||
fixme("ELF64 Unknown");
|
||||
}
|
||||
else
|
||||
fixme("Unknown ELF");
|
||||
|
||||
if (ELFHeader->e_type == ET_EXEC)
|
||||
{
|
||||
ELFLoadExec(BaseImage, ExFile->Node->Length, ELFHeader, pva, &ret, Path, Process, argv, envp, Arch, Comp);
|
||||
goto Exit;
|
||||
}
|
||||
else if (ELFHeader->e_type == ET_DYN)
|
||||
{
|
||||
fixme("Shared Object");
|
||||
}
|
||||
else if (ELFHeader->e_type == ET_REL)
|
||||
{
|
||||
trace("Relocatable");
|
||||
void *EP = ELFLoadRel(ELFHeader);
|
||||
if (EP == (void *)0xdeadbeef || EP == 0x0)
|
||||
{
|
||||
ret.Status = ExStatus::InvalidFileEntryPoint;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Vector<AuxiliaryVector> auxv;
|
||||
fixme("auxv");
|
||||
|
||||
TCB *Thread = TaskManager->CreateThread(Process,
|
||||
(IP)EP,
|
||||
argv, envp, auxv,
|
||||
(IPOffset)BaseImage,
|
||||
Arch,
|
||||
Comp);
|
||||
ret.Process = Process;
|
||||
ret.Thread = Thread;
|
||||
ret.Status = ExStatus::OK;
|
||||
goto Exit;
|
||||
}
|
||||
else if (ELFHeader->e_type == ET_CORE)
|
||||
{
|
||||
fixme("Core");
|
||||
}
|
||||
else
|
||||
{
|
||||
fixme("Unknown");
|
||||
}
|
||||
ret.Status = ExStatus::InvalidFileHeader;
|
||||
#elif defined(__i386__)
|
||||
#elif defined(__aarch64__)
|
||||
#endif
|
||||
goto Exit;
|
||||
}
|
||||
default:
|
||||
ret.Status = ExStatus::Unsupported;
|
||||
goto Exit;
|
||||
}
|
||||
ret.Status = ExStatus::InvalidFilePath;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
switch (GetBinaryType(Path))
|
||||
{
|
||||
case BinaryType::BinTypeFex:
|
||||
{
|
||||
Fex *FexHdr = (Fex *)ExFile->node->Address;
|
||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||
{
|
||||
const char *BaseName;
|
||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
|
||||
|
||||
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->node->Length));
|
||||
memcpy(BaseImage, (void *)ExFile->node->Address, ExFile->node->Length);
|
||||
|
||||
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
||||
for (size_t i = 0; i < TO_PAGES(ExFile->node->Length); i++)
|
||||
pva.Map((void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), (void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
Vector<AuxiliaryVector> auxv; // TODO!
|
||||
|
||||
TCB *Thread = TaskManager->CreateThread(Process,
|
||||
(IP)FexHdr->EntryPoint,
|
||||
argv, envp, auxv,
|
||||
(IPOffset)BaseImage,
|
||||
TaskArchitecture::x64,
|
||||
TaskCompatibility::Native);
|
||||
ret.Process = Process;
|
||||
ret.Thread = Thread;
|
||||
ret.Status = ExStatus::OK;
|
||||
}
|
||||
|
||||
ret.Status = ExStatus::InvalidFileHeader;
|
||||
goto Exit;
|
||||
}
|
||||
case BinaryType::BinTypeELF:
|
||||
{
|
||||
ELFBaseLoad bl = ELFLoad(Path, argv, envp);
|
||||
if (!bl.Success)
|
||||
{
|
||||
ret.Status = ExStatus::GenericError;
|
||||
goto Exit;
|
||||
}
|
||||
ret = bl.sd;
|
||||
goto Exit;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ret.Status = ExStatus::Unsupported;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ExFile->Status == FileSystem::FileStatus::NOT_FOUND)
|
||||
{
|
||||
else if (ExFile->Status == VirtualFileSystem::FileStatus::NotFound)
|
||||
ret.Status = ExStatus::InvalidFilePath;
|
||||
goto Exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.Status = ExStatus::InvalidFile;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (ret.Status != ExStatus::OK)
|
||||
if (ret.Process)
|
||||
ret.Process->Status = TaskStatus::Terminated;
|
||||
vfs->Close(ExFile);
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user