Merge pull request #1499 from lioncash/nro
nro/nso: Minor error handling changes
This commit is contained in:
		
						commit
						50e6205c21
					
				@ -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());
 | 
			
		||||
 | 
			
		||||
@ -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.",
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,7 @@ enum class ResultStatus : u16 {
 | 
			
		||||
    ErrorNoRomFS,
 | 
			
		||||
    ErrorIncorrectELFFileSize,
 | 
			
		||||
    ErrorLoadingNRO,
 | 
			
		||||
    ErrorLoadingNSO,
 | 
			
		||||
    ErrorNoIcon,
 | 
			
		||||
    ErrorNoControl,
 | 
			
		||||
    ErrorBadNAXHeader,
 | 
			
		||||
 | 
			
		||||
@ -127,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')) {
 | 
			
		||||
@ -138,7 +138,7 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Build program image
 | 
			
		||||
    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 {};
 | 
			
		||||
    }
 | 
			
		||||
@ -182,7 +182,7 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
 | 
			
		||||
    Core::CurrentProcess()->LoadModule(std::move(codeset), load_base);
 | 
			
		||||
 | 
			
		||||
    // Register module with GDBStub
 | 
			
		||||
    GDBStub::RegisterModule(file->GetName(), load_base, load_base);
 | 
			
		||||
    GDBStub::RegisterModule(file.GetName(), load_base, load_base);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@ -195,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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -93,17 +93,14 @@ 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'))
 | 
			
		||||
@ -114,7 +111,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base,
 | 
			
		||||
    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]);
 | 
			
		||||
        }
 | 
			
		||||
@ -157,7 +154,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base,
 | 
			
		||||
    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());
 | 
			
		||||
@ -172,7 +169,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base,
 | 
			
		||||
    Core::CurrentProcess()->LoadModule(std::move(codeset), load_base);
 | 
			
		||||
 | 
			
		||||
    // Register module with GDBStub
 | 
			
		||||
    GDBStub::RegisterModule(file->GetName(), load_base, load_base);
 | 
			
		||||
    GDBStub::RegisterModule(file.GetName(), load_base, load_base);
 | 
			
		||||
 | 
			
		||||
    return load_base + image_size;
 | 
			
		||||
}
 | 
			
		||||
@ -184,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);
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user