From 261fc73146e7d26d9e4e2803824d6a21f279e82a Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 12 Oct 2022 18:23:52 +0200 Subject: [PATCH] ELFLoader: Read the ELF file header by header using the VFS Instead of just allocating one big redundant blob of memory and reading into it, then having to free it... --- kernel/include/sys/elf/ELFLoader.h | 3 +- kernel/src/sys/elf/ELFLoader.cpp | 64 +++++++++++++----------------- 2 files changed, 30 insertions(+), 37 deletions(-) diff --git a/kernel/include/sys/elf/ELFLoader.h b/kernel/include/sys/elf/ELFLoader.h index 6fa3fe24..68d5bc97 100644 --- a/kernel/include/sys/elf/ELFLoader.h +++ b/kernel/include/sys/elf/ELFLoader.h @@ -1,10 +1,11 @@ #pragma once +#include "fs/VFS.h" #include "sys/elf/Image.h" #include namespace ELFLoader { - ELFImage* load_elf_from_address(uintptr_t addr); + ELFImage* load_elf_from_vfs(VFS::Node* node); ELFImage* load_elf_from_filesystem(const char* filename); void release_elf_image(ELFImage* image); } \ No newline at end of file diff --git a/kernel/src/sys/elf/ELFLoader.cpp b/kernel/src/sys/elf/ELFLoader.cpp index 64395567..ea3ff62c 100644 --- a/kernel/src/sys/elf/ELFLoader.cpp +++ b/kernel/src/sys/elf/ELFLoader.cpp @@ -36,80 +36,72 @@ ELFImage* ELFLoader::load_elf_from_filesystem(const char* filename) return 0; } - void* file = kmalloc(node->length); - if (VFS::read(node, 0, node->length, (char*)file) < 0) - { - kwarnln("Failed to read ELF image from file"); - kfree(file); - return 0; - } - - ELFImage* result = - load_elf_from_address((uintptr_t)file); // FIXME: Read headers and sections as we go along the file, to avoid - // loading the entire file at once into memory. - - kfree(file); - + ELFImage* result = load_elf_from_vfs(node); return result; } -ELFImage* ELFLoader::load_elf_from_address(uintptr_t addr) +ELFImage* ELFLoader::load_elf_from_vfs(VFS::Node* node) { - Elf64_Ehdr* elf_ehdr = (Elf64_Ehdr*)addr; - if (strncmp((const char*)elf_ehdr->e_ident, ELFMAG, SELFMAG) != 0) + Elf64_Ehdr elf_ehdr; + if (VFS::read(node, 0, sizeof(elf_ehdr), (char*)&elf_ehdr) < 0) + { + kwarnln("Unable to read ELF header"); + return 0; + } + if (strncmp((const char*)elf_ehdr.e_ident, ELFMAG, SELFMAG) != 0) { kwarnln("ELF file has invalid magic, skipping"); return 0; } - if (elf_ehdr->e_ident[EI_CLASS] != ELFCLASS64) + if (elf_ehdr.e_ident[EI_CLASS] != ELFCLASS64) { kwarnln("ELF file is not ELF64, skipping"); return 0; } - if (elf_ehdr->e_ident[EI_DATA] != ELFDATA2LSB) + if (elf_ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { kwarnln("ELF file is not little-endian, skipping"); return 0; } - if (elf_ehdr->e_type != ET_EXEC) + if (elf_ehdr.e_type != ET_EXEC) { kwarnln("not supported: ELF file is not an executable"); return 0; } - if (elf_ehdr->e_machine != EM_MACH) + if (elf_ehdr.e_machine != EM_MACH) { kwarnln("Unsupported target machine"); return 0; } - if (elf_ehdr->e_phnum == 0) + if (elf_ehdr.e_phnum == 0) { kwarnln("ELF file has no PHDRS"); return 0; } ELFImage* image = (ELFImage*)kmalloc(sizeof(ELFImage) - sizeof(ELFSection)); memset(image, 0, sizeof(ELFImage) - sizeof(ELFSection)); - image->entry = elf_ehdr->e_entry; + image->entry = elf_ehdr.e_entry; int i; - Elf64_Phdr* phdr; - for (phdr = (Elf64_Phdr*)((uint64_t)addr + elf_ehdr->e_phoff), i = 0; i < elf_ehdr->e_phnum; - i++, phdr = (Elf64_Phdr*)((uint8_t*)phdr + elf_ehdr->e_phentsize)) + Elf64_Phdr phdr; + for (VFS::read(node, elf_ehdr.e_phoff, sizeof(Elf64_Phdr), (char*)&phdr), i = 0; i < elf_ehdr.e_phnum; + i++, VFS::read(node, elf_ehdr.e_phoff + (i * elf_ehdr.e_phentsize), sizeof(Elf64_Phdr), (char*)&phdr)) { - if (phdr->p_type == PT_LOAD) + if (phdr.p_type == PT_LOAD) { - kdbgln("Loading loadable segment at address %lx, file size %ld, mem size %ld, permissions %s", - phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz, format_permissions(phdr->p_flags)); - if (!phdr->p_vaddr) + kdbgln("Loading loadable segment at address %lx, file size %ld, mem size %ld, permissions %s", phdr.p_vaddr, + phdr.p_filesz, phdr.p_memsz, format_permissions(phdr.p_flags)); + if (!phdr.p_vaddr) { kerrorln("Address is NULL, this is invalid :("); return 0; } - uint64_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, (phdr->p_vaddr % PAGE_SIZE) + phdr->p_memsz); + uint64_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, (phdr.p_vaddr % PAGE_SIZE) + phdr.p_memsz); void* buffer = (void*)((uint64_t)MemoryManager::get_pages_at( - Utilities::round_down_to_nearest_page(phdr->p_vaddr), pages, - phdr->p_flags & 2 ? MAP_READ_WRITE | MAP_USER : MAP_USER) + - (phdr->p_vaddr % PAGE_SIZE)); - memcpy(buffer, (void*)(addr + phdr->p_offset), phdr->p_filesz); - memset((void*)((uint64_t)buffer + phdr->p_filesz), 0, phdr->p_memsz - phdr->p_filesz); + Utilities::round_down_to_nearest_page(phdr.p_vaddr), pages, + phdr.p_flags & 2 ? MAP_READ_WRITE | MAP_USER : MAP_USER) + + (phdr.p_vaddr % PAGE_SIZE)); + VFS::read(node, phdr.p_offset, phdr.p_filesz, (char*)buffer); + memset((void*)((uint64_t)buffer + phdr.p_filesz), 0, phdr.p_memsz - phdr.p_filesz); image = (ELFImage*)krealloc(image, (sizeof(ELFImage) - sizeof(ELFSection)) + (image->section_count + 1) * sizeof(ELFSection)); ELFSection& section = image->sections[image->section_count];