summaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
authorGravatar liamwhite2024-01-15 13:52:38 -0500
committerGravatar GitHub2024-01-15 13:52:38 -0500
commit04f4eeaca2722b901a60dffd955aed993c95bd05 (patch)
treea8a16cfc59ac26bb8a56fa80d91bf311fa03810e /src/core/loader
parentMerge pull request #12665 from german77/proof (diff)
parentcore: Support multiple modules per patcher (diff)
downloadyuzu-04f4eeaca2722b901a60dffd955aed993c95bd05.tar.gz
yuzu-04f4eeaca2722b901a60dffd955aed993c95bd05.tar.xz
yuzu-04f4eeaca2722b901a60dffd955aed993c95bd05.zip
Merge pull request #12677 from GPUCode/whyy-modders
core: Support multiple modules per patcher
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp75
-rw-r--r--src/core/loader/nso.cpp41
-rw-r--r--src/core/loader/nso.h3
3 files changed, 80 insertions, 39 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 1e599e78b..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 }
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