summaryrefslogtreecommitdiff
path: root/src/core/loader/nso.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2019-03-22 13:04:41 -0400
committerGravatar Lioncash2019-03-22 14:39:10 -0400
commit1cf90f45704373cd61d274d1e3c4dc6e5be87eaa (patch)
tree7654dab9069c34d32cd14f2ae3a025b7eaeff7b2 /src/core/loader/nso.cpp
parentloader/nso: Fix definition of the NSO header struct (diff)
downloadyuzu-1cf90f45704373cd61d274d1e3c4dc6e5be87eaa.tar.gz
yuzu-1cf90f45704373cd61d274d1e3c4dc6e5be87eaa.tar.xz
yuzu-1cf90f45704373cd61d274d1e3c4dc6e5be87eaa.zip
file_sys/patch_manager: Deduplicate NSO header
This source file was utilizing its own version of the NSO header. Instead of keeping this around, we can have the patch manager also use the version of the header that we have defined in loader/nso.h
Diffstat (limited to 'src/core/loader/nso.cpp')
-rw-r--r--src/core/loader/nso.cpp68
1 files changed, 18 insertions, 50 deletions
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index a52104792..262eaeaee 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -22,47 +22,7 @@
22 22
23namespace Loader { 23namespace Loader {
24 24
25struct NsoSegmentHeader { 25struct MODHeader {
26 u32_le offset;
27 u32_le location;
28 u32_le size;
29 union {
30 u32_le alignment;
31 u32_le bss_size;
32 };
33};
34static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size.");
35
36struct NsoHeader {
37 using SHA256Hash = std::array<u8, 0x20>;
38
39 struct RODataRelativeExtent {
40 u32 data_offset;
41 u32 size;
42 };
43
44 u32_le magic;
45 u32_le version;
46 u32 reserved;
47 u32_le flags;
48 std::array<NsoSegmentHeader, 3> segments; // Text, RoData, Data (in that order)
49 std::array<u8, 0x20> build_id;
50 std::array<u32_le, 3> segments_compressed_size;
51 std::array<u8, 0x1C> padding;
52 RODataRelativeExtent api_info_extent;
53 RODataRelativeExtent dynstr_extent;
54 RODataRelativeExtent dynsyn_extent;
55 std::array<SHA256Hash, 3> segment_hashes;
56
57 bool IsSegmentCompressed(size_t segment_num) const {
58 ASSERT_MSG(segment_num < 3, "Invalid segment {}", segment_num);
59 return ((flags >> segment_num) & 1);
60 }
61};
62static_assert(sizeof(NsoHeader) == 0x100, "NsoHeader has incorrect size.");
63static_assert(std::is_trivially_copyable_v<NsoHeader>, "NsoHeader isn't trivially copyable.");
64
65struct ModHeader {
66 u32_le magic; 26 u32_le magic;
67 u32_le dynamic_offset; 27 u32_le dynamic_offset;
68 u32_le bss_start_offset; 28 u32_le bss_start_offset;
@@ -71,7 +31,12 @@ struct ModHeader {
71 u32_le eh_frame_hdr_end_offset; 31 u32_le eh_frame_hdr_end_offset;
72 u32_le module_offset; // Offset to runtime-generated module object. typically equal to .bss base 32 u32_le module_offset; // Offset to runtime-generated module object. typically equal to .bss base
73}; 33};
74static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size."); 34static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size.");
35
36bool NSOHeader::IsSegmentCompressed(size_t segment_num) const {
37 ASSERT_MSG(segment_num < 3, "Invalid segment {}", segment_num);
38 return ((flags >> segment_num) & 1) != 0;
39}
75 40
76AppLoader_NSO::AppLoader_NSO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} 41AppLoader_NSO::AppLoader_NSO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
77 42
@@ -89,7 +54,7 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
89} 54}
90 55
91static std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data, 56static std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
92 const NsoSegmentHeader& header) { 57 const NSOSegmentHeader& header) {
93 std::vector<u8> uncompressed_data(header.size); 58 std::vector<u8> uncompressed_data(header.size);
94 const int bytes_uncompressed = 59 const int bytes_uncompressed =
95 LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()), 60 LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()),
@@ -111,15 +76,18 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
111 const FileSys::VfsFile& file, VAddr load_base, 76 const FileSys::VfsFile& file, VAddr load_base,
112 bool should_pass_arguments, 77 bool should_pass_arguments,
113 std::optional<FileSys::PatchManager> pm) { 78 std::optional<FileSys::PatchManager> pm) {
114 if (file.GetSize() < sizeof(NsoHeader)) 79 if (file.GetSize() < sizeof(NSOHeader)) {
115 return {}; 80 return {};
81 }
116 82
117 NsoHeader nso_header{}; 83 NSOHeader nso_header{};
118 if (sizeof(NsoHeader) != file.ReadObject(&nso_header)) 84 if (sizeof(NSOHeader) != file.ReadObject(&nso_header)) {
119 return {}; 85 return {};
86 }
120 87
121 if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) 88 if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) {
122 return {}; 89 return {};
90 }
123 91
124 // Build program image 92 // Build program image
125 Kernel::CodeSet codeset; 93 Kernel::CodeSet codeset;
@@ -155,10 +123,10 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
155 std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32)); 123 std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32));
156 124
157 // Read MOD header 125 // Read MOD header
158 ModHeader mod_header{}; 126 MODHeader mod_header{};
159 // Default .bss to size in segment header if MOD0 section doesn't exist 127 // Default .bss to size in segment header if MOD0 section doesn't exist
160 u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)}; 128 u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)};
161 std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader)); 129 std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(MODHeader));
162 const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')}; 130 const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')};
163 if (has_mod_header) { 131 if (has_mod_header) {
164 // Resize program image to include .bss section and page align each section 132 // Resize program image to include .bss section and page align each section
@@ -171,7 +139,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
171 // Apply patches if necessary 139 // Apply patches if necessary
172 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) { 140 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
173 std::vector<u8> pi_header(program_image.size() + 0x100); 141 std::vector<u8> pi_header(program_image.size() + 0x100);
174 std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader)); 142 std::memcpy(pi_header.data(), &nso_header, sizeof(NSOHeader));
175 std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size()); 143 std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size());
176 144
177 pi_header = pm->PatchNSO(pi_header); 145 pi_header = pm->PatchNSO(pi_header);