summaryrefslogtreecommitdiff
path: root/src/core/loader/nso.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader/nso.cpp')
-rw-r--r--src/core/loader/nso.cpp54
1 files changed, 23 insertions, 31 deletions
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 044067a5b..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"
@@ -47,7 +47,7 @@ std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
47} 47}
48 48
49constexpr u32 PageAlignSize(u32 size) { 49constexpr u32 PageAlignSize(u32 size) {
50 return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; 50 return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
51} 51}
52} // Anonymous namespace 52} // Anonymous namespace
53 53
@@ -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 {};
@@ -97,21 +97,17 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
97 if (nso_header.IsSegmentCompressed(i)) { 97 if (nso_header.IsSegmentCompressed(i)) {
98 data = DecompressSegment(data, nso_header.segments[i]); 98 data = DecompressSegment(data, nso_header.segments[i]);
99 } 99 }
100 program_image.resize(nso_header.segments[i].location + 100 program_image.resize(nso_header.segments[i].location + static_cast<u32>(data.size()));
101 PageAlignSize(static_cast<u32>(data.size())));
102 std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(), 101 std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(),
103 data.size()); 102 data.size());
104 codeset.segments[i].addr = nso_header.segments[i].location; 103 codeset.segments[i].addr = nso_header.segments[i].location;
105 codeset.segments[i].offset = nso_header.segments[i].location; 104 codeset.segments[i].offset = nso_header.segments[i].location;
106 codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size())); 105 codeset.segments[i].size = nso_header.segments[i].size;
107 } 106 }
108 107
109 if (should_pass_arguments) { 108 if (should_pass_arguments && !Settings::values.program_args.empty()) {
110 std::vector<u8> arg_data{Settings::values.program_args.begin(), 109 const auto arg_data{Settings::values.program_args};
111 Settings::values.program_args.end()}; 110
112 if (arg_data.empty()) {
113 arg_data.resize(NSO_ARGUMENT_DEFAULT_SIZE);
114 }
115 codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; 111 codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
116 NSOArgumentHeader args_header{ 112 NSOArgumentHeader args_header{
117 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()), {}};
@@ -123,24 +119,15 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
123 arg_data.size()); 119 arg_data.size());
124 } 120 }
125 121
126 // MOD header pointer is at .text offset + 4 122 codeset.DataSegment().size += nso_header.segments[2].bss_size;
127 u32 module_offset; 123 const u32 image_size{
128 std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32)); 124 PageAlignSize(static_cast<u32>(program_image.size()) + nso_header.segments[2].bss_size)};
129
130 // Read MOD header
131 MODHeader mod_header{};
132 // Default .bss to size in segment header if MOD0 section doesn't exist
133 u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)};
134 std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(MODHeader));
135 const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')};
136 if (has_mod_header) {
137 // Resize program image to include .bss section and page align each section
138 bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset);
139 }
140 codeset.DataSegment().size += bss_size;
141 const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)};
142 program_image.resize(image_size); 125 program_image.resize(image_size);
143 126
127 for (std::size_t i = 0; i < nso_header.segments.size(); ++i) {
128 codeset.segments[i].size = PageAlignSize(codeset.segments[i].size);
129 }
130
144 // Apply patches if necessary 131 // Apply patches if necessary
145 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) { 132 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
146 std::vector<u8> pi_header; 133 std::vector<u8> pi_header;
@@ -154,6 +141,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
154 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());
155 } 142 }
156 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
157 // 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
158 if (pm) { 150 if (pm) {
159 auto& system = Core::System::GetInstance(); 151 auto& system = Core::System::GetInstance();
@@ -182,8 +174,8 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
182 modules.clear(); 174 modules.clear();
183 175
184 // Load module 176 // Load module
185 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 177 const VAddr base_address = process.PageTable().GetCodeRegionStart();
186 if (!LoadModule(process, *file, base_address, true)) { 178 if (!LoadModule(process, *file, base_address, true, true)) {
187 return {ResultStatus::ErrorLoadingNSO, {}}; 179 return {ResultStatus::ErrorLoadingNSO, {}};
188 } 180 }
189 181
@@ -192,7 +184,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
192 184
193 is_loaded = true; 185 is_loaded = true;
194 return {ResultStatus::Success, 186 return {ResultStatus::Success,
195 LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}}; 187 LoadParameters{Kernel::THREADPRIO_DEFAULT, Core::Memory::DEFAULT_STACK_SIZE}};
196} 188}
197 189
198ResultStatus AppLoader_NSO::ReadNSOModules(Modules& modules) { 190ResultStatus AppLoader_NSO::ReadNSOModules(Modules& modules) {