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...
This commit is contained in:
parent
7a2e313a20
commit
261fc73146
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "fs/VFS.h"
|
||||||
#include "sys/elf/Image.h"
|
#include "sys/elf/Image.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace ELFLoader
|
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);
|
ELFImage* load_elf_from_filesystem(const char* filename);
|
||||||
void release_elf_image(ELFImage* image);
|
void release_elf_image(ELFImage* image);
|
||||||
}
|
}
|
@ -36,80 +36,72 @@ ELFImage* ELFLoader::load_elf_from_filesystem(const char* filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* file = kmalloc(node->length);
|
ELFImage* result = load_elf_from_vfs(node);
|
||||||
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);
|
|
||||||
|
|
||||||
return result;
|
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;
|
Elf64_Ehdr elf_ehdr;
|
||||||
if (strncmp((const char*)elf_ehdr->e_ident, ELFMAG, SELFMAG) != 0)
|
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");
|
kwarnln("ELF file has invalid magic, skipping");
|
||||||
return 0;
|
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");
|
kwarnln("ELF file is not ELF64, skipping");
|
||||||
return 0;
|
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");
|
kwarnln("ELF file is not little-endian, skipping");
|
||||||
return 0;
|
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");
|
kwarnln("not supported: ELF file is not an executable");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (elf_ehdr->e_machine != EM_MACH)
|
if (elf_ehdr.e_machine != EM_MACH)
|
||||||
{
|
{
|
||||||
kwarnln("Unsupported target machine");
|
kwarnln("Unsupported target machine");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (elf_ehdr->e_phnum == 0)
|
if (elf_ehdr.e_phnum == 0)
|
||||||
{
|
{
|
||||||
kwarnln("ELF file has no PHDRS");
|
kwarnln("ELF file has no PHDRS");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ELFImage* image = (ELFImage*)kmalloc(sizeof(ELFImage) - sizeof(ELFSection));
|
ELFImage* image = (ELFImage*)kmalloc(sizeof(ELFImage) - sizeof(ELFSection));
|
||||||
memset(image, 0, 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;
|
int i;
|
||||||
Elf64_Phdr* phdr;
|
Elf64_Phdr phdr;
|
||||||
for (phdr = (Elf64_Phdr*)((uint64_t)addr + elf_ehdr->e_phoff), i = 0; i < elf_ehdr->e_phnum;
|
for (VFS::read(node, elf_ehdr.e_phoff, sizeof(Elf64_Phdr), (char*)&phdr), i = 0; i < elf_ehdr.e_phnum;
|
||||||
i++, phdr = (Elf64_Phdr*)((uint8_t*)phdr + elf_ehdr->e_phentsize))
|
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",
|
kdbgln("Loading loadable segment at address %lx, file size %ld, mem size %ld, permissions %s", phdr.p_vaddr,
|
||||||
phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz, format_permissions(phdr->p_flags));
|
phdr.p_filesz, phdr.p_memsz, format_permissions(phdr.p_flags));
|
||||||
if (!phdr->p_vaddr)
|
if (!phdr.p_vaddr)
|
||||||
{
|
{
|
||||||
kerrorln("Address is NULL, this is invalid :(");
|
kerrorln("Address is NULL, this is invalid :(");
|
||||||
return 0;
|
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(
|
void* buffer = (void*)((uint64_t)MemoryManager::get_pages_at(
|
||||||
Utilities::round_down_to_nearest_page(phdr->p_vaddr), pages,
|
Utilities::round_down_to_nearest_page(phdr.p_vaddr), pages,
|
||||||
phdr->p_flags & 2 ? MAP_READ_WRITE | MAP_USER : MAP_USER) +
|
phdr.p_flags & 2 ? MAP_READ_WRITE | MAP_USER : MAP_USER) +
|
||||||
(phdr->p_vaddr % PAGE_SIZE));
|
(phdr.p_vaddr % PAGE_SIZE));
|
||||||
memcpy(buffer, (void*)(addr + phdr->p_offset), phdr->p_filesz);
|
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);
|
memset((void*)((uint64_t)buffer + phdr.p_filesz), 0, phdr.p_memsz - phdr.p_filesz);
|
||||||
image = (ELFImage*)krealloc(image, (sizeof(ELFImage) - sizeof(ELFSection)) +
|
image = (ELFImage*)krealloc(image, (sizeof(ELFImage) - sizeof(ELFSection)) +
|
||||||
(image->section_count + 1) * sizeof(ELFSection));
|
(image->section_count + 1) * sizeof(ELFSection));
|
||||||
ELFSection& section = image->sections[image->section_count];
|
ELFSection& section = image->sections[image->section_count];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user