Merge pull request #1499 from lioncash/nro

nro/nso: Minor error handling changes
This commit is contained in:
bunnei 2018-10-15 17:48:36 -04:00 committed by GitHub
commit 50e6205c21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 28 deletions

View file

@ -139,14 +139,22 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
"subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
const FileSys::VirtualFile module_file = dir->GetFile(module); const FileSys::VirtualFile module_file = dir->GetFile(module);
if (module_file != nullptr) { if (module_file == nullptr) {
const VAddr load_addr = next_load_addr; continue;
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);
} }
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()); process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize());

View file

@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) {
return "unknown"; return "unknown";
} }
constexpr std::array<const char*, 59> RESULT_MESSAGES{ constexpr std::array<const char*, 60> RESULT_MESSAGES{
"The operation completed successfully.", "The operation completed successfully.",
"The loader requested to load is already loaded.", "The loader requested to load is already loaded.",
"The operation is not implemented.", "The operation is not implemented.",
@ -128,6 +128,7 @@ constexpr std::array<const char*, 59> RESULT_MESSAGES{
"The RomFS could not be found.", "The RomFS could not be found.",
"The ELF file has incorrect size as determined by the header.", "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 NRO into emulated memory.",
"There was a general error loading the NSO into emulated memory.",
"There is no icon available.", "There is no icon available.",
"There is no control data available.", "There is no control data available.",
"The NAX file has a bad header.", "The NAX file has a bad header.",

View file

@ -90,6 +90,7 @@ enum class ResultStatus : u16 {
ErrorNoRomFS, ErrorNoRomFS,
ErrorIncorrectELFFileSize, ErrorIncorrectELFFileSize,
ErrorLoadingNRO, ErrorLoadingNRO,
ErrorLoadingNSO,
ErrorNoIcon, ErrorNoIcon,
ErrorNoControl, ErrorNoControl,
ErrorBadNAXHeader, ErrorBadNAXHeader,

View file

@ -127,10 +127,10 @@ static constexpr u32 PageAlignSize(u32 size) {
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; 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 // Read NSO header
NroHeader nro_header{}; NroHeader nro_header{};
if (sizeof(NroHeader) != file->ReadObject(&nro_header)) { if (sizeof(NroHeader) != file.ReadObject(&nro_header)) {
return {}; return {};
} }
if (nro_header.magic != Common::MakeMagic('N', 'R', 'O', '0')) { 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 // 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)) { if (program_image.size() != PageAlignSize(nro_header.file_size)) {
return {}; return {};
} }
@ -182,7 +182,7 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); Core::CurrentProcess()->LoadModule(std::move(codeset), load_base);
// Register module with GDBStub // Register module with GDBStub
GDBStub::RegisterModule(file->GetName(), load_base, load_base); GDBStub::RegisterModule(file.GetName(), load_base, load_base);
return true; return true;
} }
@ -195,7 +195,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::Process& process) {
// Load NRO // Load NRO
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
if (!LoadNro(file, base_address)) { if (!LoadNro(*file, base_address)) {
return ResultStatus::ErrorLoadingNRO; return ResultStatus::ErrorLoadingNRO;
} }

View file

@ -41,7 +41,7 @@ public:
bool IsRomFSUpdatable() const override; bool IsRomFSUpdatable() const override;
private: private:
bool LoadNro(FileSys::VirtualFile file, VAddr load_base); bool LoadNro(const FileSys::VfsFile& file, VAddr load_base);
std::vector<u8> icon_data; std::vector<u8> icon_data;
std::unique_ptr<FileSys::NACP> nacp; std::unique_ptr<FileSys::NACP> nacp;

View file

@ -93,17 +93,14 @@ static constexpr u32 PageAlignSize(u32 size) {
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
} }
VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAddr load_base,
bool should_pass_arguments, bool should_pass_arguments,
boost::optional<FileSys::PatchManager> pm) { std::optional<FileSys::PatchManager> pm) {
if (file == nullptr) if (file.GetSize() < sizeof(NsoHeader))
return {};
if (file->GetSize() < sizeof(NsoHeader))
return {}; return {};
NsoHeader nso_header{}; NsoHeader nso_header{};
if (sizeof(NsoHeader) != file->ReadObject(&nso_header)) if (sizeof(NsoHeader) != file.ReadObject(&nso_header))
return {}; return {};
if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) 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; std::vector<u8> program_image;
for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { for (std::size_t i = 0; i < nso_header.segments.size(); ++i) {
std::vector<u8> data = 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)) { if (nso_header.IsSegmentCompressed(i)) {
data = DecompressSegment(data, nso_header.segments[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); program_image.resize(image_size);
// Apply patches if necessary // 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::vector<u8> pi_header(program_image.size() + 0x100);
std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader)); std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader));
std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size()); 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); Core::CurrentProcess()->LoadModule(std::move(codeset), load_base);
// Register module with GDBStub // 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; return load_base + image_size;
} }
@ -184,7 +181,9 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) {
// Load module // Load module
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 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); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <optional>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/file_sys/patch_manager.h" #include "core/file_sys/patch_manager.h"
#include "core/loader/linker.h" #include "core/loader/linker.h"
@ -36,8 +37,9 @@ public:
return IdentifyType(file); return IdentifyType(file);
} }
static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, bool should_pass_arguments, static std::optional<VAddr> LoadModule(const FileSys::VfsFile& file, VAddr load_base,
boost::optional<FileSys::PatchManager> pm = boost::none); bool should_pass_arguments,
std::optional<FileSys::PatchManager> pm = {});
ResultStatus Load(Kernel::Process& process) override; ResultStatus Load(Kernel::Process& process) override;
}; };