summaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp89
-rw-r--r--src/core/loader/nca.cpp6
-rw-r--r--src/core/loader/nro.cpp10
-rw-r--r--src/core/loader/nso.cpp41
-rw-r--r--src/core/loader/nso.h3
-rw-r--r--src/core/loader/nsp.cpp3
-rw-r--r--src/core/loader/xci.cpp3
7 files changed, 94 insertions, 61 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index c9f8707b7..9b75c660c 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -19,8 +19,54 @@
19#include "core/arm/nce/patcher.h" 19#include "core/arm/nce/patcher.h"
20#endif 20#endif
21 21
22#ifndef HAS_NCE
23namespace Core::NCE {
24class Patcher {};
25} // namespace Core::NCE
26#endif
27
22namespace Loader { 28namespace Loader {
23 29
30struct PatchCollection {
31 explicit PatchCollection(bool is_application_) : is_application{is_application_} {
32 module_patcher_indices.fill(-1);
33 patchers.emplace_back();
34 }
35
36 std::vector<Core::NCE::Patcher>* GetPatchers() {
37 if (is_application && Settings::IsNceEnabled()) {
38 return &patchers;
39 }
40 return nullptr;
41 }
42
43 size_t GetTotalPatchSize() const {
44 size_t total_size{};
45#ifdef HAS_NCE
46 for (auto& patcher : patchers) {
47 total_size += patcher.GetSectionSize();
48 }
49#endif
50 return total_size;
51 }
52
53 void SaveIndex(size_t module) {
54 module_patcher_indices[module] = static_cast<s32>(patchers.size() - 1);
55 }
56
57 s32 GetIndex(size_t module) const {
58 return module_patcher_indices[module];
59 }
60
61 s32 GetLastIndex() const {
62 return static_cast<s32>(patchers.size()) - 1;
63 }
64
65 bool is_application;
66 std::vector<Core::NCE::Patcher> patchers;
67 std::array<s32, 13> module_patcher_indices{};
68};
69
24AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, 70AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_,
25 bool override_update_) 71 bool override_update_)
26 : AppLoader(std::move(file_)), override_update(override_update_), is_hbl(false) { 72 : AppLoader(std::move(file_)), override_update(override_update_), is_hbl(false) {
@@ -142,18 +188,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
142 std::size_t code_size{}; 188 std::size_t code_size{};
143 189
144 // Define an nce patch context for each potential module. 190 // Define an nce patch context for each potential module.
145#ifdef HAS_NCE 191 PatchCollection patch_ctx{is_application};
146 std::array<Core::NCE::Patcher, 13> module_patchers;
147#endif
148
149 const auto GetPatcher = [&](size_t i) -> Core::NCE::Patcher* {
150#ifdef HAS_NCE
151 if (is_application && Settings::IsNceEnabled()) {
152 return &module_patchers[i];
153 }
154#endif
155 return nullptr;
156 };
157 192
158 // Use the NSO module loader to figure out the code layout 193 // Use the NSO module loader to figure out the code layout
159 for (size_t i = 0; i < static_modules.size(); i++) { 194 for (size_t i = 0; i < static_modules.size(); i++) {
@@ -164,13 +199,14 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
164 } 199 }
165 200
166 const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; 201 const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
167 const auto tentative_next_load_addr = 202 const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
168 AppLoader_NSO::LoadModule(process, system, *module_file, code_size, 203 process, system, *module_file, code_size, should_pass_arguments, false, {},
169 should_pass_arguments, false, {}, GetPatcher(i)); 204 patch_ctx.GetPatchers(), patch_ctx.GetLastIndex());
170 if (!tentative_next_load_addr) { 205 if (!tentative_next_load_addr) {
171 return {ResultStatus::ErrorLoadingNSO, {}}; 206 return {ResultStatus::ErrorLoadingNSO, {}};
172 } 207 }
173 208
209 patch_ctx.SaveIndex(i);
174 code_size = *tentative_next_load_addr; 210 code_size = *tentative_next_load_addr;
175 } 211 }
176 212
@@ -184,6 +220,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
184 return 0; 220 return 0;
185 }(); 221 }();
186 222
223 // Add patch size to the total module size
224 code_size += patch_ctx.GetTotalPatchSize();
225
187 // Setup the process code layout 226 // Setup the process code layout
188 if (process.LoadFromMetadata(metadata, code_size, fastmem_base, is_hbl).IsError()) { 227 if (process.LoadFromMetadata(metadata, code_size, fastmem_base, is_hbl).IsError()) {
189 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; 228 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
@@ -204,9 +243,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
204 243
205 const VAddr load_addr{next_load_addr}; 244 const VAddr load_addr{next_load_addr};
206 const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; 245 const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
207 const auto tentative_next_load_addr = 246 const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
208 AppLoader_NSO::LoadModule(process, system, *module_file, load_addr, 247 process, system, *module_file, load_addr, should_pass_arguments, true, pm,
209 should_pass_arguments, true, pm, GetPatcher(i)); 248 patch_ctx.GetPatchers(), patch_ctx.GetIndex(i));
210 if (!tentative_next_load_addr) { 249 if (!tentative_next_load_addr) {
211 return {ResultStatus::ErrorLoadingNSO, {}}; 250 return {ResultStatus::ErrorLoadingNSO, {}};
212 } 251 }
@@ -216,20 +255,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
216 LOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr); 255 LOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr);
217 } 256 }
218 257
219 // Find the RomFS by searching for a ".romfs" file in this directory
220 const auto& files = dir->GetFiles();
221 const auto romfs_iter =
222 std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& f) {
223 return f->GetName().find(".romfs") != std::string::npos;
224 });
225
226 // Register the RomFS if a ".romfs" file was found
227 if (romfs_iter != files.end() && *romfs_iter != nullptr) {
228 romfs = *romfs_iter;
229 system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
230 *this, system.GetContentProvider(), system.GetFileSystemController()));
231 }
232
233 is_loaded = true; 258 is_loaded = true;
234 return {ResultStatus::Success, 259 return {ResultStatus::Success,
235 LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}}; 260 LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}};
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 814407535..2a32b1276 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -74,8 +74,10 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::KProcess& process, Core::S
74 return load_result; 74 return load_result;
75 } 75 }
76 76
77 system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>( 77 system.GetFileSystemController().RegisterProcess(
78 *this, system.GetContentProvider(), system.GetFileSystemController())); 78 process.GetProcessId(), nca->GetTitleId(),
79 std::make_shared<FileSys::RomFSFactory>(*this, system.GetContentProvider(),
80 system.GetFileSystemController()));
79 81
80 is_loaded = true; 82 is_loaded = true;
81 return load_result; 83 return load_result;
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index e74697cda..f8225d697 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -275,10 +275,12 @@ AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::KProcess& process, Core::S
275 return {ResultStatus::ErrorLoadingNRO, {}}; 275 return {ResultStatus::ErrorLoadingNRO, {}};
276 } 276 }
277 277
278 if (romfs != nullptr) { 278 u64 program_id{};
279 system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>( 279 ReadProgramId(program_id);
280 *this, system.GetContentProvider(), system.GetFileSystemController())); 280 system.GetFileSystemController().RegisterProcess(
281 } 281 process.GetProcessId(), program_id,
282 std::make_unique<FileSys::RomFSFactory>(*this, system.GetContentProvider(),
283 system.GetFileSystemController()));
282 284
283 is_loaded = true; 285 is_loaded = true;
284 return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority, 286 return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority,
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index b053a0d14..583b7e927 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -77,7 +77,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
77 const FileSys::VfsFile& nso_file, VAddr load_base, 77 const FileSys::VfsFile& nso_file, VAddr load_base,
78 bool should_pass_arguments, bool load_into_process, 78 bool should_pass_arguments, bool load_into_process,
79 std::optional<FileSys::PatchManager> pm, 79 std::optional<FileSys::PatchManager> pm,
80 Core::NCE::Patcher* patch) { 80 std::vector<Core::NCE::Patcher>* patches,
81 s32 patch_index) {
81 if (nso_file.GetSize() < sizeof(NSOHeader)) { 82 if (nso_file.GetSize() < sizeof(NSOHeader)) {
82 return std::nullopt; 83 return std::nullopt;
83 } 84 }
@@ -94,8 +95,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
94 // Allocate some space at the beginning if we are patching in PreText mode. 95 // Allocate some space at the beginning if we are patching in PreText mode.
95 const size_t module_start = [&]() -> size_t { 96 const size_t module_start = [&]() -> size_t {
96#ifdef HAS_NCE 97#ifdef HAS_NCE
97 if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::PreText) { 98 if (patches && load_into_process) {
98 return patch->GetSectionSize(); 99 auto* patch = &patches->operator[](patch_index);
100 if (patch->GetPatchMode() == Core::NCE::PatchMode::PreText) {
101 return patch->GetSectionSize();
102 }
99 } 103 }
100#endif 104#endif
101 return 0; 105 return 0;
@@ -160,27 +164,24 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
160#ifdef HAS_NCE 164#ifdef HAS_NCE
161 // If we are computing the process code layout and using nce backend, patch. 165 // If we are computing the process code layout and using nce backend, patch.
162 const auto& code = codeset.CodeSegment(); 166 const auto& code = codeset.CodeSegment();
163 if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::None) { 167 auto* patch = patches ? &patches->operator[](patch_index) : nullptr;
168 if (patch && !load_into_process) {
164 // Patch SVCs and MRS calls in the guest code 169 // Patch SVCs and MRS calls in the guest code
165 patch->PatchText(program_image, code); 170 while (!patch->PatchText(program_image, code)) {
166 171 patch = &patches->emplace_back();
167 // Add patch section size to the module size. 172 }
168 image_size += static_cast<u32>(patch->GetSectionSize());
169 } else if (patch) { 173 } else if (patch) {
170 // Relocate code patch and copy to the program_image. 174 // Relocate code patch and copy to the program_image.
171 patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers()); 175 if (patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers())) {
172 176 // Update patch section.
173 // Update patch section. 177 auto& patch_segment = codeset.PatchSegment();
174 auto& patch_segment = codeset.PatchSegment(); 178 patch_segment.addr =
175 patch_segment.addr = 179 patch->GetPatchMode() == Core::NCE::PatchMode::PreText ? 0 : image_size;
176 patch->GetPatchMode() == Core::NCE::PatchMode::PreText ? 0 : image_size; 180 patch_segment.size = static_cast<u32>(patch->GetSectionSize());
177 patch_segment.size = static_cast<u32>(patch->GetSectionSize());
178
179 // Add patch section size to the module size. In PreText mode image_size
180 // already contains the patch segment as part of module_start.
181 if (patch->GetPatchMode() == Core::NCE::PatchMode::PostData) {
182 image_size += patch_segment.size;
183 } 181 }
182
183 // Refresh image_size to take account the patch section if it was added by RelocateAndCopy
184 image_size = static_cast<u32>(program_image.size());
184 } 185 }
185#endif 186#endif
186 187
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index 29b86ed4c..6356697e3 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -93,7 +93,8 @@ public:
93 const FileSys::VfsFile& nso_file, VAddr load_base, 93 const FileSys::VfsFile& nso_file, VAddr load_base,
94 bool should_pass_arguments, bool load_into_process, 94 bool should_pass_arguments, bool load_into_process,
95 std::optional<FileSys::PatchManager> pm = {}, 95 std::optional<FileSys::PatchManager> pm = {},
96 Core::NCE::Patcher* patch = nullptr); 96 std::vector<Core::NCE::Patcher>* patches = nullptr,
97 s32 patch_index = -1);
97 98
98 LoadResult Load(Kernel::KProcess& process, Core::System& system) override; 99 LoadResult Load(Kernel::KProcess& process, Core::System& system) override;
99 100
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index f4ab75b77..28116ff3a 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -111,7 +111,8 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
111 111
112 FileSys::VirtualFile update_raw; 112 FileSys::VirtualFile update_raw;
113 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { 113 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
114 system.GetFileSystemController().SetPackedUpdate(std::move(update_raw)); 114 system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(),
115 std::move(update_raw));
115 } 116 }
116 117
117 is_loaded = true; 118 is_loaded = true;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 12d72c380..e9abb199a 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -78,7 +78,8 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::KProcess& process, Core::S
78 78
79 FileSys::VirtualFile update_raw; 79 FileSys::VirtualFile update_raw;
80 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { 80 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
81 system.GetFileSystemController().SetPackedUpdate(std::move(update_raw)); 81 system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(),
82 std::move(update_raw));
82 } 83 }
83 84
84 is_loaded = true; 85 is_loaded = true;