diff options
Diffstat (limited to 'src/core/loader')
-rw-r--r-- | src/core/loader/deconstructed_rom_directory.cpp | 22 | ||||
-rw-r--r-- | src/core/loader/elf.cpp | 32 | ||||
-rw-r--r-- | src/core/loader/loader.cpp | 3 | ||||
-rw-r--r-- | src/core/loader/loader.h | 1 | ||||
-rw-r--r-- | src/core/loader/nro.cpp | 29 | ||||
-rw-r--r-- | src/core/loader/nro.h | 2 | ||||
-rw-r--r-- | src/core/loader/nso.cpp | 42 | ||||
-rw-r--r-- | src/core/loader/nso.h | 6 |
8 files changed, 68 insertions, 69 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 951fd8257..8518dddcb 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -139,14 +139,22 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { const FileSys::VirtualFile module_file = dir->GetFile(module); - if (module_file != nullptr) { - const VAddr load_addr = next_load_addr; - next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr, - std::strcmp(module, "rtld") == 0, pm); - LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); - // Register module with GDBStub - GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); + if (module_file == nullptr) { + continue; } + + const VAddr load_addr = next_load_addr; + const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; + const auto tentative_next_load_addr = + AppLoader_NSO::LoadModule(*module_file, load_addr, should_pass_arguments, pm); + if (!tentative_next_load_addr) { + return ResultStatus::ErrorLoadingNSO; + } + + next_load_addr = *tentative_next_load_addr; + LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); + // Register module with GDBStub + GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); } process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()); diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index e67b49fc9..6057c7f26 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -9,16 +9,11 @@ #include "common/common_types.h" #include "common/file_util.h" #include "common/logging/log.h" -#include "core/core.h" -#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/vm_manager.h" #include "core/loader/elf.h" #include "core/memory.h" -using Kernel::CodeSet; -using Kernel::SharedPtr; - //////////////////////////////////////////////////////////////////////////////////////////////////// // ELF Header Constants @@ -211,7 +206,7 @@ public: u32 GetFlags() const { return (u32)(header->e_flags); } - SharedPtr<CodeSet> LoadInto(VAddr vaddr); + Kernel::CodeSet LoadInto(VAddr vaddr); int GetNumSegments() const { return (int)(header->e_phnum); @@ -274,7 +269,7 @@ const char* ElfReader::GetSectionName(int section) const { return nullptr; } -SharedPtr<CodeSet> ElfReader::LoadInto(VAddr vaddr) { +Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) { LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); // Should we relocate? @@ -302,8 +297,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(VAddr vaddr) { std::vector<u8> program_image(total_image_size); std::size_t current_image_position = 0; - auto& kernel = Core::System::GetInstance().Kernel(); - SharedPtr<CodeSet> codeset = CodeSet::Create(kernel, ""); + Kernel::CodeSet codeset; for (unsigned int i = 0; i < header->e_phnum; ++i) { const Elf32_Phdr* p = &segments[i]; @@ -311,14 +305,14 @@ SharedPtr<CodeSet> ElfReader::LoadInto(VAddr vaddr) { p->p_vaddr, p->p_filesz, p->p_memsz); if (p->p_type == PT_LOAD) { - CodeSet::Segment* codeset_segment; + Kernel::CodeSet::Segment* codeset_segment; u32 permission_flags = p->p_flags & (PF_R | PF_W | PF_X); if (permission_flags == (PF_R | PF_X)) { - codeset_segment = &codeset->CodeSegment(); + codeset_segment = &codeset.CodeSegment(); } else if (permission_flags == (PF_R)) { - codeset_segment = &codeset->RODataSegment(); + codeset_segment = &codeset.RODataSegment(); } else if (permission_flags == (PF_R | PF_W)) { - codeset_segment = &codeset->DataSegment(); + codeset_segment = &codeset.DataSegment(); } else { LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i, p->p_flags); @@ -345,8 +339,8 @@ SharedPtr<CodeSet> ElfReader::LoadInto(VAddr vaddr) { } } - codeset->entrypoint = base_addr + header->e_entry; - codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); + codeset.entrypoint = base_addr + header->e_entry; + codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); LOG_DEBUG(Loader, "Done loading."); @@ -397,11 +391,11 @@ ResultStatus AppLoader_ELF::Load(Kernel::Process& process) { const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); ElfReader elf_reader(&buffer[0]); - SharedPtr<CodeSet> codeset = elf_reader.LoadInto(base_address); - codeset->name = file->GetName(); + Kernel::CodeSet codeset = elf_reader.LoadInto(base_address); + const VAddr entry_point = codeset.entrypoint; - process.LoadModule(codeset, codeset->entrypoint); - process.Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE); + process.LoadModule(std::move(codeset), entry_point); + process.Run(entry_point, 48, Memory::DEFAULT_STACK_SIZE); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 91659ec17..9cd0b0ccd 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) { return "unknown"; } -constexpr std::array<const char*, 59> RESULT_MESSAGES{ +constexpr std::array<const char*, 60> RESULT_MESSAGES{ "The operation completed successfully.", "The loader requested to load is already loaded.", "The operation is not implemented.", @@ -128,6 +128,7 @@ constexpr std::array<const char*, 59> RESULT_MESSAGES{ "The RomFS could not be found.", "The ELF file has incorrect size as determined by the header.", "There was a general error loading the NRO into emulated memory.", + "There was a general error loading the NSO into emulated memory.", "There is no icon available.", "There is no control data available.", "The NAX file has a bad header.", diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 0e0333db5..e562b3a04 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -90,6 +90,7 @@ enum class ResultStatus : u16 { ErrorNoRomFS, ErrorIncorrectELFFileSize, ErrorLoadingNRO, + ErrorLoadingNSO, ErrorNoIcon, ErrorNoControl, ErrorBadNAXHeader, diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 25dd3f04e..243b499f2 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -14,7 +14,6 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/vfs_offset.h" #include "core/gdbstub/gdbstub.h" -#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/vm_manager.h" #include "core/loader/nro.h" @@ -128,10 +127,10 @@ static constexpr u32 PageAlignSize(u32 size) { return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; } -bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { +bool AppLoader_NRO::LoadNro(const FileSys::VfsFile& file, VAddr load_base) { // Read NSO header NroHeader nro_header{}; - if (sizeof(NroHeader) != file->ReadObject(&nro_header)) { + if (sizeof(NroHeader) != file.ReadObject(&nro_header)) { return {}; } if (nro_header.magic != Common::MakeMagic('N', 'R', 'O', '0')) { @@ -139,22 +138,21 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { } // Build program image - auto& kernel = Core::System::GetInstance().Kernel(); - Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(kernel, ""); - std::vector<u8> program_image = file->ReadBytes(PageAlignSize(nro_header.file_size)); + std::vector<u8> program_image = file.ReadBytes(PageAlignSize(nro_header.file_size)); if (program_image.size() != PageAlignSize(nro_header.file_size)) { return {}; } + Kernel::CodeSet codeset; for (std::size_t i = 0; i < nro_header.segments.size(); ++i) { - codeset->segments[i].addr = nro_header.segments[i].offset; - codeset->segments[i].offset = nro_header.segments[i].offset; - codeset->segments[i].size = PageAlignSize(nro_header.segments[i].size); + codeset.segments[i].addr = nro_header.segments[i].offset; + codeset.segments[i].offset = nro_header.segments[i].offset; + codeset.segments[i].size = PageAlignSize(nro_header.segments[i].size); } if (!Settings::values.program_args.empty()) { const auto arg_data = Settings::values.program_args; - codeset->DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; + codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; NSOArgumentHeader args_header{ NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; const auto end_offset = program_image.size(); @@ -176,16 +174,15 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { // Resize program image to include .bss section and page align each section bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset); } - codeset->DataSegment().size += bss_size; + codeset.DataSegment().size += bss_size; program_image.resize(static_cast<u32>(program_image.size()) + bss_size); // Load codeset for current process - codeset->name = file->GetName(); - codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); - Core::CurrentProcess()->LoadModule(codeset, load_base); + codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); + Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); // Register module with GDBStub - GDBStub::RegisterModule(codeset->name, load_base, load_base); + GDBStub::RegisterModule(file.GetName(), load_base, load_base); return true; } @@ -198,7 +195,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { // Load NRO const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); - if (!LoadNro(file, base_address)) { + if (!LoadNro(*file, base_address)) { return ResultStatus::ErrorLoadingNRO; } diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h index 04b46119a..50ee5a78a 100644 --- a/src/core/loader/nro.h +++ b/src/core/loader/nro.h @@ -41,7 +41,7 @@ public: bool IsRomFSUpdatable() const override; private: - bool LoadNro(FileSys::VirtualFile file, VAddr load_base); + bool LoadNro(const FileSys::VfsFile& file, VAddr load_base); std::vector<u8> icon_data; std::unique_ptr<FileSys::NACP> nacp; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 28c6dd9b7..68efca5c0 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -12,7 +12,6 @@ #include "core/core.h" #include "core/file_sys/patch_manager.h" #include "core/gdbstub/gdbstub.h" -#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/vm_manager.h" #include "core/loader/nso.h" @@ -94,42 +93,38 @@ static constexpr u32 PageAlignSize(u32 size) { return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; } -VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, - bool should_pass_arguments, - boost::optional<FileSys::PatchManager> pm) { - if (file == nullptr) - return {}; - - if (file->GetSize() < sizeof(NsoHeader)) +std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAddr load_base, + bool should_pass_arguments, + std::optional<FileSys::PatchManager> pm) { + if (file.GetSize() < sizeof(NsoHeader)) return {}; NsoHeader nso_header{}; - if (sizeof(NsoHeader) != file->ReadObject(&nso_header)) + if (sizeof(NsoHeader) != file.ReadObject(&nso_header)) return {}; if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) return {}; // Build program image - auto& kernel = Core::System::GetInstance().Kernel(); - Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(kernel, ""); + Kernel::CodeSet codeset; std::vector<u8> program_image; for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { std::vector<u8> data = - file->ReadBytes(nso_header.segments_compressed_size[i], nso_header.segments[i].offset); + file.ReadBytes(nso_header.segments_compressed_size[i], nso_header.segments[i].offset); if (nso_header.IsSegmentCompressed(i)) { data = DecompressSegment(data, nso_header.segments[i]); } program_image.resize(nso_header.segments[i].location); program_image.insert(program_image.end(), data.begin(), data.end()); - codeset->segments[i].addr = nso_header.segments[i].location; - codeset->segments[i].offset = nso_header.segments[i].location; - codeset->segments[i].size = PageAlignSize(static_cast<u32>(data.size())); + codeset.segments[i].addr = nso_header.segments[i].location; + codeset.segments[i].offset = nso_header.segments[i].location; + codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size())); } if (should_pass_arguments && !Settings::values.program_args.empty()) { const auto arg_data = Settings::values.program_args; - codeset->DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; + codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; NSOArgumentHeader args_header{ NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; const auto end_offset = program_image.size(); @@ -154,12 +149,12 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, // Resize program image to include .bss section and page align each section bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset); } - codeset->DataSegment().size += bss_size; + codeset.DataSegment().size += bss_size; const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)}; program_image.resize(image_size); // Apply patches if necessary - if (pm != boost::none && pm->HasNSOPatch(nso_header.build_id)) { + if (pm && pm->HasNSOPatch(nso_header.build_id)) { std::vector<u8> pi_header(program_image.size() + 0x100); std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader)); std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size()); @@ -170,12 +165,11 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, } // Load codeset for current process - codeset->name = file->GetName(); - codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); - Core::CurrentProcess()->LoadModule(codeset, load_base); + codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); + Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); // Register module with GDBStub - GDBStub::RegisterModule(codeset->name, load_base, load_base); + GDBStub::RegisterModule(file.GetName(), load_base, load_base); return load_base + image_size; } @@ -187,7 +181,9 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { // Load module const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); - LoadModule(file, base_address, true); + if (!LoadModule(*file, base_address, true)) { + return ResultStatus::ErrorLoadingNSO; + } LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 70ab3b718..433306139 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h @@ -4,6 +4,7 @@ #pragma once +#include <optional> #include "common/common_types.h" #include "core/file_sys/patch_manager.h" #include "core/loader/linker.h" @@ -36,8 +37,9 @@ public: return IdentifyType(file); } - static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, bool should_pass_arguments, - boost::optional<FileSys::PatchManager> pm = boost::none); + static std::optional<VAddr> LoadModule(const FileSys::VfsFile& file, VAddr load_base, + bool should_pass_arguments, + std::optional<FileSys::PatchManager> pm = {}); ResultStatus Load(Kernel::Process& process) override; }; |