From 3b1d05eccea373c1f63e60064dda7d3b5633a9f9 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 3 Aug 2025 11:36:28 +0300 Subject: [PATCH] Re-add ELF support --- src/core/loader/elf.cpp | 103 ++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index ec1c70b9..205b16ec 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -4,63 +4,64 @@ #include "memory.hpp" using namespace ELFIO; +using namespace KernelMemoryTypes; std::optional Memory::loadELF(std::ifstream& file) { - /* loadedCXI = std::nullopt; // ELF files don't have a CXI, so set this to null + loadedCXI = std::nullopt; // ELF files don't have a CXI, so set this to null - elfio reader; - if (!file.good() || !reader.load(file)) { - printf("Woops failed to load ELF\n"); - return std::nullopt; + elfio reader; + if (!file.good() || !reader.load(file)) { + printf("Woops failed to load ELF\n"); + return std::nullopt; + } + + // Allocate stack space. For ELFs we use the default stack size, which is 16KB + if (!allocateMainThreadStack(VirtualAddrs::DefaultStackSize)) { + // Should be unreachable + printf("Failed to allocate stack space for ELF file\n"); + return std::nullopt; + } + + auto segNum = reader.segments.size(); + printf("Number of segments: %d\n", segNum); + printf(" # Perms Vaddr File Size Mem Size\n"); + + for (int i = 0; i < segNum; ++i) { + const auto seg = reader.segments[i]; + const auto flags = seg->get_flags(); + const u32 vaddr = static_cast(seg->get_virtual_address()); // Vaddr the segment is loaded in + u32 fileSize = static_cast(seg->get_file_size()); // Size of segment in file + u32 memorySize = static_cast(seg->get_memory_size()); // Size of segment in memory + u8* data = (u8*)seg->get_data(); + + // Get read/write/execute permissions for segment + const bool r = (flags & 0b100) != 0; + const bool w = (flags & 0b010) != 0; + const bool x = (flags & 0b001) != 0; + + printf("[%d] (%c%c%c)\t%08X\t%08X\t%08X\n", i, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', vaddr, fileSize, memorySize); + + // Assert that the segment will be loaded in the executable region. If it isn't then panic. + // The executable region starts at 0x00100000 and has a maximum size of 0x03F00000 + u64 endAddress = (u64)vaddr + (u64)fileSize; + const bool isGood = vaddr >= VirtualAddrs::ExecutableStart && endAddress < VirtualAddrs::ExecutableEnd; + if (!isGood) { + // We're ignoring this for now because some ELFs define a segment at the vaddr for IPC buffer mapping + // Helpers::panic("ELF is loaded at invalid place"); + // return std::nullopt; } - // Allocate stack space. For ELFs we use the default stack size, which is 16KB - if (!allocateMainThreadStack(VirtualAddrs::DefaultStackSize)) { - // Should be unreachable - printf("Failed to allocate stack space for ELF file\n"); - return std::nullopt; + if (memorySize & pageMask) { + // Round up the size of the ELF segment to a page (4KB) boundary, as the OS can only alloc this way + memorySize = (memorySize + pageSize - 1) & -pageSize; + Helpers::warn("Rounding ELF segment size to %08X\n", memorySize); } - auto segNum = reader.segments.size(); - printf("Number of segments: %d\n", segNum); - printf(" # Perms Vaddr File Size Mem Size\n"); - for (int i = 0; i < segNum; ++i) { - const auto seg = reader.segments[i]; - const auto flags = seg->get_flags(); - const u32 vaddr = static_cast(seg->get_virtual_address()); // Vaddr the segment is loaded in - u32 fileSize = static_cast(seg->get_file_size()); // Size of segment in file - u32 memorySize = static_cast(seg->get_memory_size()); // Size of segment in memory - u8* data = (u8*)seg->get_data(); + allocMemory(vaddr, memorySize / Memory::pageSize, FcramRegion::App, r, w, x, MemoryState::Code); + copyToVaddr(vaddr, data, fileSize); + } - // Get read/write/execute permissions for segment - const bool r = (flags & 0b100) != 0; - const bool w = (flags & 0b010) != 0; - const bool x = (flags & 0b001) != 0; - - printf("[%d] (%c%c%c)\t%08X\t%08X\t%08X\n", i, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', vaddr, fileSize, memorySize); - - // Assert that the segment will be loaded in the executable region. If it isn't then panic. - // The executable region starts at 0x00100000 and has a maximum size of 0x03F00000 - u64 endAddress = (u64)vaddr + (u64)fileSize; - const bool isGood = vaddr >= VirtualAddrs::ExecutableStart && endAddress < VirtualAddrs::ExecutableEnd; - if (!isGood) { - // We're ignoring this for now because some ELFs define a segment at the vaddr for IPC buffer mapping - // Helpers::panic("ELF is loaded at invalid place"); - // return std::nullopt; - } - - if (memorySize & pageMask) { - // Round up the size of the ELF segment to a page (4KB) boundary, as the OS can only alloc this way - memorySize = (memorySize + pageSize - 1) & -pageSize; - Helpers::warn("Rounding ELF segment size to %08X\n", memorySize); - } - - // This should also assert that findPaddr doesn't fail - u32 fcramAddr = findPaddr(memorySize).value(); - std::memcpy(&fcram[fcramAddr], data, fileSize); - - // ELF can't specify a region, make it default to USA - region = Regions::USA; - return static_cast(reader.get_entry());*/ - return std::nullopt; + // ELF can't specify a region, make it default to USA + region = Regions::USA; + return static_cast(reader.get_entry()); } \ No newline at end of file