loader: nso: Fix loader size and arguments.
This commit is contained in:
parent
83761d5316
commit
bebfb05c1b
3 changed files with 51 additions and 29 deletions
|
@ -14,6 +14,7 @@
|
||||||
#include "core/file_sys/romfs_factory.h"
|
#include "core/file_sys/romfs_factory.h"
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/deconstructed_rom_directory.h"
|
#include "core/loader/deconstructed_rom_directory.h"
|
||||||
|
@ -129,27 +130,47 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||||
}
|
}
|
||||||
metadata.Print();
|
metadata.Print();
|
||||||
|
|
||||||
if (process.LoadFromMetadata(metadata).IsError()) {
|
const auto static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
|
||||||
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
"subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"};
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::PatchManager pm(metadata.GetTitleID());
|
// Use the NSO module loader to figure out the code layout
|
||||||
|
std::size_t code_size{};
|
||||||
// Load NSO modules
|
for (const auto& module : static_modules) {
|
||||||
modules.clear();
|
const FileSys::VirtualFile module_file{dir->GetFile(module)};
|
||||||
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
if (!module_file) {
|
||||||
VAddr next_load_addr = base_address;
|
|
||||||
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) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VAddr load_addr = next_load_addr;
|
const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
|
||||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
|
||||||
const auto tentative_next_load_addr =
|
process, *module_file, code_size, should_pass_arguments, false)};
|
||||||
AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm);
|
if (!tentative_next_load_addr) {
|
||||||
|
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
code_size = *tentative_next_load_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the process code layout
|
||||||
|
if (process.LoadFromMetadata(metadata, code_size).IsError()) {
|
||||||
|
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load NSO modules
|
||||||
|
modules.clear();
|
||||||
|
const VAddr base_address{process.PageTable().GetCodeRegionStart()};
|
||||||
|
VAddr next_load_addr{base_address};
|
||||||
|
const FileSys::PatchManager pm{metadata.GetTitleID()};
|
||||||
|
for (const auto& module : static_modules) {
|
||||||
|
const FileSys::VirtualFile module_file{dir->GetFile(module)};
|
||||||
|
if (!module_file) {
|
||||||
|
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(
|
||||||
|
process, *module_file, load_addr, should_pass_arguments, true, pm)};
|
||||||
if (!tentative_next_load_addr) {
|
if (!tentative_next_load_addr) {
|
||||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/vm_manager.h"
|
|
||||||
#include "core/loader/nso.h"
|
#include "core/loader/nso.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
@ -73,7 +73,7 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||||
|
|
||||||
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
const FileSys::VfsFile& file, VAddr load_base,
|
const FileSys::VfsFile& file, VAddr load_base,
|
||||||
bool should_pass_arguments,
|
bool should_pass_arguments, bool load_into_process,
|
||||||
std::optional<FileSys::PatchManager> pm) {
|
std::optional<FileSys::PatchManager> pm) {
|
||||||
if (file.GetSize() < sizeof(NSOHeader)) {
|
if (file.GetSize() < sizeof(NSOHeader)) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -105,12 +105,9 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
codeset.segments[i].size = nso_header.segments[i].size;
|
codeset.segments[i].size = nso_header.segments[i].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_pass_arguments) {
|
if (should_pass_arguments && !Settings::values.program_args.empty()) {
|
||||||
std::vector<u8> arg_data{Settings::values.program_args.begin(),
|
const auto arg_data{Settings::values.program_args};
|
||||||
Settings::values.program_args.end()};
|
|
||||||
if (arg_data.empty()) {
|
|
||||||
arg_data.resize(NSO_ARGUMENT_DEFAULT_SIZE);
|
|
||||||
}
|
|
||||||
codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
|
codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
|
||||||
NSOArgumentHeader args_header{
|
NSOArgumentHeader args_header{
|
||||||
NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}};
|
NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}};
|
||||||
|
@ -144,6 +141,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
|
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we aren't actually loading (i.e. just computing the process code layout), we are done
|
||||||
|
if (!load_into_process) {
|
||||||
|
return load_base + image_size;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply cheats if they exist and the program has a valid title ID
|
// Apply cheats if they exist and the program has a valid title ID
|
||||||
if (pm) {
|
if (pm) {
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
|
@ -172,8 +174,8 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
|
||||||
modules.clear();
|
modules.clear();
|
||||||
|
|
||||||
// Load module
|
// Load module
|
||||||
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
|
const VAddr base_address = process.PageTable().GetCodeRegionStart();
|
||||||
if (!LoadModule(process, *file, base_address, true)) {
|
if (!LoadModule(process, *file, base_address, true, true)) {
|
||||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,6 @@ static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
|
||||||
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
||||||
|
|
||||||
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||||
// NOTE: Official software default argument state is unverified.
|
|
||||||
constexpr u64 NSO_ARGUMENT_DEFAULT_SIZE = 1;
|
|
||||||
|
|
||||||
struct NSOArgumentHeader {
|
struct NSOArgumentHeader {
|
||||||
u32_le allocated_size;
|
u32_le allocated_size;
|
||||||
|
@ -84,6 +82,7 @@ public:
|
||||||
|
|
||||||
static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file,
|
static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file,
|
||||||
VAddr load_base, bool should_pass_arguments,
|
VAddr load_base, bool should_pass_arguments,
|
||||||
|
bool load_into_process,
|
||||||
std::optional<FileSys::PatchManager> pm = {});
|
std::optional<FileSys::PatchManager> pm = {});
|
||||||
|
|
||||||
LoadResult Load(Kernel::Process& process) override;
|
LoadResult Load(Kernel::Process& process) override;
|
||||||
|
|
Loading…
Reference in a new issue