diff options
Diffstat (limited to 'src/core/loader/nso.cpp')
| -rw-r--r-- | src/core/loader/nso.cpp | 54 |
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 | ||
| 49 | constexpr u32 PageAlignSize(u32 size) { | 49 | constexpr 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 | ||
| 74 | std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | 74 | std::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 | ||
| 198 | ResultStatus AppLoader_NSO::ReadNSOModules(Modules& modules) { | 190 | ResultStatus AppLoader_NSO::ReadNSOModules(Modules& modules) { |