From f2eab6c64f5e583311e1bb937f6f30ee11aa8e2c Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 21 Apr 2023 17:47:09 +0300 Subject: [PATCH] Fix elf loading --- Core/Memory/StackGuard.cpp | 6 ++- Execute/Elf/Parse.cpp | 18 ++++--- Execute/Elf/SharedObjects.cpp | 89 +++++++++++++++++++++++++++++++++++ SystemCalls/Native.cpp | 28 +++++------ include/exec.hpp | 2 +- 5 files changed, 119 insertions(+), 24 deletions(-) diff --git a/Core/Memory/StackGuard.cpp b/Core/Memory/StackGuard.cpp index e0f613f..0d38ff1 100644 --- a/Core/Memory/StackGuard.cpp +++ b/Core/Memory/StackGuard.cpp @@ -32,9 +32,10 @@ namespace Memory memset(AllocatedStack, 0, USER_STACK_SIZE); debug("AllocatedStack: %p", AllocatedStack); + Virtual va = Virtual(Table); for (size_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++) { - Virtual(Table).Map((void *)(USER_STACK_BASE + (i * PAGE_SIZE)), + va.Map((void *)(USER_STACK_BASE + (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US); @@ -88,9 +89,10 @@ namespace Memory void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE + 1)); debug("AllocatedStack: %p", AllocatedStack); memset(AllocatedStack, 0, USER_STACK_SIZE); + Virtual va = Virtual(this->Table); for (uintptr_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++) { - Virtual(this->Table).Map((void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US); + va.Map((void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US); debug("Mapped %p to %p", (void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE))); } this->StackBottom = (void *)((uintptr_t)this->StackBottom - USER_STACK_SIZE); diff --git a/Execute/Elf/Parse.cpp b/Execute/Elf/Parse.cpp index 40a3397..6356277 100644 --- a/Execute/Elf/Parse.cpp +++ b/Execute/Elf/Parse.cpp @@ -51,7 +51,7 @@ namespace Execute return StringTable + Offset; } - void *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) + Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) { Elf64_Shdr *SymbolTable = nullptr; Elf64_Shdr *StringTable = nullptr; @@ -82,7 +82,7 @@ namespace Execute 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 Symbol; } return nullptr; } @@ -108,7 +108,7 @@ namespace Execute 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); + void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value; if (Target == nullptr) { if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK) @@ -165,6 +165,8 @@ namespace Execute { void *MemoryImage = nullptr; Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; + bool IsPIC = ELFHeader->e_type == ET_DYN; + debug("Elf %s PIC", IsPIC ? "is" : "is not"); /* TODO: Not sure what I am supposed to do with this. * It is supposed to detect if it's PIC or not but I @@ -195,15 +197,17 @@ namespace Execute 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 + 1), true); + debug("p_vaddr is 0, allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); + MemoryImage = mem->RequestPages(TO_PAGES(Length), true); + debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); memset(MemoryImage, 0, Length); return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; } } - debug("Allocating %ld pages for image", TO_PAGES(Length)); - MemoryImage = mem->RequestPages(TO_PAGES(Length + 1)); + debug("Allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); + MemoryImage = mem->RequestPages(TO_PAGES(Length)); + debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); memset(MemoryImage, 0, Length); if (FirstProgramHeaderVirtualAddress != 0) diff --git a/Execute/Elf/SharedObjects.cpp b/Execute/Elf/SharedObjects.cpp index 63ef35e..8b7f2b7 100644 --- a/Execute/Elf/SharedObjects.cpp +++ b/Execute/Elf/SharedObjects.cpp @@ -127,6 +127,95 @@ namespace Execute debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)LibFile + ItrProgramHeader.p_offset, (uintptr_t)MAddr, ItrProgramHeader.p_filesz); break; } + + struct Elf64_Dyn *JmpRel = ELFGetDynamicTag((void *)LibFile, DT_JMPREL); + struct Elf64_Dyn *SymTab = ELFGetDynamicTag((void *)LibFile, DT_SYMTAB); + struct Elf64_Dyn *StrTab = ELFGetDynamicTag((void *)LibFile, DT_STRTAB); + + if (!JmpRel) + { + debug("No DT_JMPREL"); + } + + if (!SymTab) + { + debug("No DT_SYMTAB"); + } + + if (!StrTab) + { + debug("No DT_STRTAB"); + } + + if (JmpRel && SymTab && StrTab) + { + debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", JmpRel->d_un.d_ptr, SymTab->d_un.d_ptr, StrTab->d_un.d_ptr); + Elf64_Rela *_JmpRel = (Elf64_Rela *)(sl.MemoryImage + (JmpRel->d_un.d_ptr - BaseAddress)); + Elf64_Sym *_SymTab = (Elf64_Sym *)(sl.MemoryImage + (SymTab->d_un.d_ptr - BaseAddress)); + + char *_DynStr = (char *)(sl.MemoryImage + (StrTab->d_un.d_ptr - BaseAddress)); + + Elf64_Shdr *gotSection = nullptr; + for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_shnum; i++) + { + Elf64_Shdr *shdr = (Elf64_Shdr *)((uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_shoff + i * sizeof(Elf64_Shdr)); + if (shdr->sh_type == SHT_PROGBITS && (shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC)) + { + gotSection = shdr; + break; + } + } + + debug("LIB_DBG"); + + if (gotSection) + { + Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr); + for (Elf64_Xword i = 0; i < numEntries - 3; i++) + { + Elf64_Rela *Rel = _JmpRel + i; + Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + sl.MemoryImage); + + Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info); + debug("r_offset: %#lx RelType: %d", Rel->r_offset, RelType); + + switch (RelType) + { + case R_X86_64_NONE: + break; + case R_X86_64_JUMP_SLOT: + { + Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info); + Elf64_Sym *Sym = _SymTab + SymIndex; + + if (Sym->st_name) + { + char *SymName = _DynStr + Sym->st_name; + debug("SymName: %s", SymName); + + Elf64_Sym *LibSym = ELFLookupSymbol((Elf64_Ehdr *)LibFile, SymName); + + if (LibSym) + { + *GOTEntry = (Elf64_Addr)(sl.MemoryImage + LibSym->st_value); + debug("GOT[%ld]: %#lx + %#lx = %#lx", i, sl.MemoryImage, LibSym->st_value, *GOTEntry); + } + } + break; + } + default: + { + fixme("RelType %d not supported", RelType); + break; + } + } + + debug("GOT[%ld](%#lx): %#lx", i, GOTEntry, *GOTEntry); + } + } + else + debug("GOT section not found"); + } } sl.Address = r_cst(uint64_t, LibFile); diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index 3acf52e..5f304c3 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -188,7 +188,7 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t if (!lib.Address) debug("Failed to get library address %#lx", (uintptr_t)lib.Address); - debug("Returning library address %#lx", (uintptr_t)lib.Address); + debug("Returning library address %#lx (%s)", (uintptr_t)lib.Address, Identifier); return (uintptr_t)lib.Address; } case KCTL_GET_ELF_LIB_MEMORY_IMAGE: @@ -202,7 +202,7 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t if (!lib.MemoryImage) debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage); - debug("Returning memory image %#lx", (uintptr_t)lib.MemoryImage); + debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier); return (uintptr_t)lib.MemoryImage; } default: @@ -228,28 +228,28 @@ static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType T return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size); } -static int sys_file_open(SyscallsFrame *Frame) +static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t Flags) { - fixme("sys_file_open: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("%s, %#lx", Path, Flags); + return 0; } -static int sys_file_close(SyscallsFrame *Frame) +static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate) { - fixme("sys_file_close: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("%#lx", KernelPrivate); + return SYSCALL_OK; } -static int sys_file_read(SyscallsFrame *Frame) +static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size) { - fixme("sys_file_read: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("%#lx, %#lx, %#lx, %#lx, %#lx", Frame, KernelPrivate, Offset, Buffer, Size); + return 0; } -static int sys_file_write(SyscallsFrame *Frame) +static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size) { - fixme("sys_file_write: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("%#lx, %#lx, %#lx, %#lx, %#lx", Frame, KernelPrivate, Offset, Buffer, Size); + return 0; } static int sys_file_seek(SyscallsFrame *Frame) diff --git a/include/exec.hpp b/include/exec.hpp index 2c62429..25b3ca7 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -107,7 +107,7 @@ namespace Execute Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index); char *GetELFStringTable(Elf64_Ehdr *Header); char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset); - void *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name); + Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name); uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index); Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag);