summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp47
-rw-r--r--src/core/loader/nso.cpp22
-rw-r--r--src/core/loader/nso.h3
3 files changed, 47 insertions, 25 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 53559e8b1..134e83412 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -14,6 +14,7 @@
14#include "core/file_sys/romfs_factory.h" 14#include "core/file_sys/romfs_factory.h"
15#include "core/gdbstub/gdbstub.h" 15#include "core/gdbstub/gdbstub.h"
16#include "core/hle/kernel/kernel.h" 16#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/memory/page_table.h"
17#include "core/hle/kernel/process.h" 18#include "core/hle/kernel/process.h"
18#include "core/hle/service/filesystem/filesystem.h" 19#include "core/hle/service/filesystem/filesystem.h"
19#include "core/loader/deconstructed_rom_directory.h" 20#include "core/loader/deconstructed_rom_directory.h"
@@ -129,27 +130,47 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
129 } 130 }
130 metadata.Print(); 131 metadata.Print();
131 132
132 if (process.LoadFromMetadata(metadata).IsError()) { 133 const auto static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
133 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; 134 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"};
135
136 // Use the NSO module loader to figure out the code layout
137 std::size_t code_size{};
138 for (const auto& module : static_modules) {
139 const FileSys::VirtualFile module_file{dir->GetFile(module)};
140 if (!module_file) {
141 continue;
142 }
143
144 const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
145 const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
146 process, *module_file, code_size, should_pass_arguments, false)};
147 if (!tentative_next_load_addr) {
148 return {ResultStatus::ErrorLoadingNSO, {}};
149 }
150
151 code_size = *tentative_next_load_addr;
134 } 152 }
135 153
136 const FileSys::PatchManager pm(metadata.GetTitleID()); 154 // Setup the process code layout
155 if (process.LoadFromMetadata(metadata, code_size).IsError()) {
156 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
157 }
137 158
138 // Load NSO modules 159 // Load NSO modules
139 modules.clear(); 160 modules.clear();
140 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 161 const VAddr base_address{process.PageTable().GetCodeRegionStart()};
141 VAddr next_load_addr = base_address; 162 VAddr next_load_addr{base_address};
142 for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", 163 const FileSys::PatchManager pm{metadata.GetTitleID()};
143 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { 164 for (const auto& module : static_modules) {
144 const FileSys::VirtualFile module_file = dir->GetFile(module); 165 const FileSys::VirtualFile module_file{dir->GetFile(module)};
145 if (module_file == nullptr) { 166 if (!module_file) {
146 continue; 167 continue;
147 } 168 }
148 169
149 const VAddr load_addr = next_load_addr; 170 const VAddr load_addr{next_load_addr};
150 const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; 171 const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
151 const auto tentative_next_load_addr = 172 const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
152 AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm); 173 process, *module_file, load_addr, should_pass_arguments, true, pm)};
153 if (!tentative_next_load_addr) { 174 if (!tentative_next_load_addr) {
154 return {ResultStatus::ErrorLoadingNSO, {}}; 175 return {ResultStatus::ErrorLoadingNSO, {}};
155 } 176 }
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index ce9d52309..612ff9bf6 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -16,8 +16,8 @@
16#include "core/file_sys/patch_manager.h" 16#include "core/file_sys/patch_manager.h"
17#include "core/gdbstub/gdbstub.h" 17#include "core/gdbstub/gdbstub.h"
18#include "core/hle/kernel/code_set.h" 18#include "core/hle/kernel/code_set.h"
19#include "core/hle/kernel/memory/page_table.h"
19#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/vm_manager.h"
21#include "core/loader/nso.h" 21#include "core/loader/nso.h"
22#include "core/memory.h" 22#include "core/memory.h"
23#include "core/settings.h" 23#include "core/settings.h"
@@ -73,7 +73,7 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
73 73
74std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, 74std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
75 const FileSys::VfsFile& file, VAddr load_base, 75 const FileSys::VfsFile& file, VAddr load_base,
76 bool should_pass_arguments, 76 bool should_pass_arguments, bool load_into_process,
77 std::optional<FileSys::PatchManager> pm) { 77 std::optional<FileSys::PatchManager> pm) {
78 if (file.GetSize() < sizeof(NSOHeader)) { 78 if (file.GetSize() < sizeof(NSOHeader)) {
79 return {}; 79 return {};
@@ -105,12 +105,9 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
105 codeset.segments[i].size = nso_header.segments[i].size; 105 codeset.segments[i].size = nso_header.segments[i].size;
106 } 106 }
107 107
108 if (should_pass_arguments) { 108 if (should_pass_arguments && !Settings::values.program_args.empty()) {
109 std::vector<u8> arg_data{Settings::values.program_args.begin(), 109 const auto arg_data{Settings::values.program_args};
110 Settings::values.program_args.end()}; 110
111 if (arg_data.empty()) {
112 arg_data.resize(NSO_ARGUMENT_DEFAULT_SIZE);
113 }
114 codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; 111 codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
115 NSOArgumentHeader args_header{ 112 NSOArgumentHeader args_header{
116 NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; 113 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,
144 std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data()); 141 std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
145 } 142 }
146 143
144 // If we aren't actually loading (i.e. just computing the process code layout), we are done
145 if (!load_into_process) {
146 return load_base + image_size;
147 }
148
147 // Apply cheats if they exist and the program has a valid title ID 149 // Apply cheats if they exist and the program has a valid title ID
148 if (pm) { 150 if (pm) {
149 auto& system = Core::System::GetInstance(); 151 auto& system = Core::System::GetInstance();
@@ -172,8 +174,8 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
172 modules.clear(); 174 modules.clear();
173 175
174 // Load module 176 // Load module
175 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 177 const VAddr base_address = process.PageTable().GetCodeRegionStart();
176 if (!LoadModule(process, *file, base_address, true)) { 178 if (!LoadModule(process, *file, base_address, true, true)) {
177 return {ResultStatus::ErrorLoadingNSO, {}}; 179 return {ResultStatus::ErrorLoadingNSO, {}};
178 } 180 }
179 181
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index d2d600cd9..b210830f0 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -56,8 +56,6 @@ static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
56static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable."); 56static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
57 57
58constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000; 58constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
59// NOTE: Official software default argument state is unverified.
60constexpr u64 NSO_ARGUMENT_DEFAULT_SIZE = 1;
61 59
62struct NSOArgumentHeader { 60struct NSOArgumentHeader {
63 u32_le allocated_size; 61 u32_le allocated_size;
@@ -84,6 +82,7 @@ public:
84 82
85 static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file, 83 static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file,
86 VAddr load_base, bool should_pass_arguments, 84 VAddr load_base, bool should_pass_arguments,
85 bool load_into_process,
87 std::optional<FileSys::PatchManager> pm = {}); 86 std::optional<FileSys::PatchManager> pm = {});
88 87
89 LoadResult Load(Kernel::Process& process) override; 88 LoadResult Load(Kernel::Process& process) override;