From 2b1cc232bce45e12d466fc606f78b484bb13a3a8 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 31 May 2020 18:49:51 +0200 Subject: [PATCH 01/12] ldr: Update NRR/NRO structs This was based on Switchbrew pages: https://switchbrew.org/wiki/NRR https://switchbrew.org/wiki/NRO --- src/core/hle/service/ldr/ldr.cpp | 112 ++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 6ad3be1b33..62d4bfc086 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -39,47 +39,68 @@ constexpr ResultCode ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87}; constexpr std::size_t MAXIMUM_LOADED_RO{0x40}; constexpr std::size_t MAXIMUM_MAP_RETRIES{0x200}; +struct Certification { + u64_le application_id_mask; + u64_le application_id_pattern; + std::array reserved; + std::array public_key; // Also known as modulus + std::array signature; +}; +static_assert(sizeof(Certification) == 0x220, "Certification has invalid size!"); + +using SHA256Hash = std::array; + struct NRRHeader { u32_le magic; - INSERT_PADDING_BYTES(12); - u64_le title_id_mask; - u64_le title_id_pattern; - INSERT_PADDING_BYTES(16); - std::array modulus; - std::array signature_1; - std::array signature_2; - u64_le title_id; + u32_le certification_signature_key_generation; // 9.0.0+ + u64_le reserved; + Certification certification; + std::array signature; + u64_le application_id; u32_le size; - INSERT_PADDING_BYTES(4); + u8 nrr_kind; + std::array reserved_2; u32_le hash_offset; u32_le hash_count; - INSERT_PADDING_BYTES(8); + u64_le reserved_3; + + // Must be dynamically allocated because, according to + // SwitchBrew, its size is (0x20 * hash_count) and + // it's impossible to determine the value of hash_count + // (SwitchBrew calls it "NumHash") before runtime, + // therefore it's not possible to calculate a SHA-256 + std::vector NroHashList; }; -static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has incorrect size."); + +struct SegmentHeader { + u32_le memory_offset; + u32_le memory_size; +}; +static_assert(sizeof(SegmentHeader) == 0x8, "SegmentHeader has invalid size!"); struct NROHeader { - INSERT_PADDING_WORDS(1); + // Switchbrew calls this "Start" (0x10) + u32_le unused; u32_le mod_offset; - INSERT_PADDING_WORDS(2); + u64_le padding; + + // Switchbrew calls this "Header" (0x70) u32_le magic; u32_le version; u32_le nro_size; u32_le flags; - u32_le text_offset; - u32_le text_size; - u32_le ro_offset; - u32_le ro_size; - u32_le rw_offset; - u32_le rw_size; + // .text, .ro, .data (yuzu previously called it "rw" instead of "data") + std::array segment_headers; u32_le bss_size; - INSERT_PADDING_WORDS(1); + u32_le reserved; std::array build_id; - INSERT_PADDING_BYTES(0x20); + u32_le dso_handle_offset; + u32_le unused_2; + // .apiInfo, .dynstr, .dynsym + std::array segment_headers_2; }; static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size."); -using SHA256Hash = std::array; - struct NROInfo { SHA256Hash hash{}; VAddr nro_address{}; @@ -226,11 +247,11 @@ public: return; } - if (system.CurrentProcess()->GetTitleID() != header.title_id) { + if (system.CurrentProcess()->GetTitleID() != header.application_id) { LOG_ERROR(Service_LDR, "Attempting to load NRR with title ID other than current process. (actual " "{:016X})!", - header.title_id); + header.application_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERROR_INVALID_NRR); return; @@ -348,10 +369,10 @@ public: ResultCode LoadNro(Kernel::Process* process, const NROHeader& nro_header, VAddr nro_addr, VAddr start) const { - const VAddr text_start{start + nro_header.text_offset}; - const VAddr ro_start{start + nro_header.ro_offset}; - const VAddr data_start{start + nro_header.rw_offset}; - const VAddr bss_start{data_start + nro_header.rw_size}; + const VAddr text_start{start + nro_header.segment_headers[0].memory_offset}; + const VAddr ro_start{start + nro_header.segment_headers[1].memory_offset}; + const VAddr data_start{start + nro_header.segment_headers[2].memory_offset}; + const VAddr bss_start{data_start + nro_header.segment_headers[2].memory_size}; const VAddr bss_end_addr{ Common::AlignUp(bss_start + nro_header.bss_size, Kernel::Memory::PageSize)}; @@ -360,9 +381,12 @@ public: system.Memory().ReadBlock(src_addr, source_data.data(), source_data.size()); system.Memory().WriteBlock(dst_addr, source_data.data(), source_data.size()); }}; - CopyCode(nro_addr + nro_header.text_offset, text_start, nro_header.text_size); - CopyCode(nro_addr + nro_header.ro_offset, ro_start, nro_header.ro_size); - CopyCode(nro_addr + nro_header.rw_offset, data_start, nro_header.rw_size); + CopyCode(nro_addr + nro_header.segment_headers[0].memory_offset, text_start, + nro_header.segment_headers[0].memory_size); + CopyCode(nro_addr + nro_header.segment_headers[1].memory_offset, ro_start, + nro_header.segment_headers[1].memory_size); + CopyCode(nro_addr + nro_header.segment_headers[2].memory_offset, data_start, + nro_header.segment_headers[2].memory_size); CASCADE_CODE(process->PageTable().SetCodeMemoryPermission( text_start, ro_start - text_start, Kernel::Memory::MemoryPermission::ReadAndExecute)); @@ -484,9 +508,11 @@ public: } // Track the loaded NRO - nro.insert_or_assign(*map_result, NROInfo{hash, *map_result, nro_size, bss_address, - bss_size, header.text_size, header.ro_size, - header.rw_size, nro_address}); + nro.insert_or_assign(*map_result, + NROInfo{hash, *map_result, nro_size, bss_address, bss_size, + header.segment_headers[0].memory_size, + header.segment_headers[1].memory_size, + header.segment_headers[2].memory_size, nro_address}); // Invalidate JIT caches for the newly mapped process code system.InvalidateCpuInstructionCaches(); @@ -584,11 +610,17 @@ private: static bool IsValidNRO(const NROHeader& header, u64 nro_size, u64 bss_size) { return header.magic == Common::MakeMagic('N', 'R', 'O', '0') && header.nro_size == nro_size && header.bss_size == bss_size && - header.ro_offset == header.text_offset + header.text_size && - header.rw_offset == header.ro_offset + header.ro_size && - nro_size == header.rw_offset + header.rw_size && - Common::Is4KBAligned(header.text_size) && Common::Is4KBAligned(header.ro_size) && - Common::Is4KBAligned(header.rw_size); + header.segment_headers[1].memory_offset == + header.segment_headers[0].memory_offset + + header.segment_headers[0].memory_size && + header.segment_headers[2].memory_offset == + header.segment_headers[1].memory_offset + + header.segment_headers[1].memory_size && + nro_size == header.segment_headers[2].memory_offset + + header.segment_headers[2].memory_size && + Common::Is4KBAligned(header.segment_headers[0].memory_size) && + Common::Is4KBAligned(header.segment_headers[1].memory_size) && + Common::Is4KBAligned(header.segment_headers[2].memory_size); } Core::System& system; }; From a087b3365a26b14ea6733b213998df5ff318afb3 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 31 May 2020 19:12:09 +0200 Subject: [PATCH 02/12] Add comment to nrr_kind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Atmosphére (https://github.com/Atmosphere-NX/Atmosphere/blob/c7026b90940a1d88f9c10a6d98263bf22e654fa5/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp), nrr_kind (Atmosphére calls it "type") is 7.0.0+ --- src/core/hle/service/ldr/ldr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 62d4bfc086..252b79d2c7 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -58,7 +58,7 @@ struct NRRHeader { std::array signature; u64_le application_id; u32_le size; - u8 nrr_kind; + u8 nrr_kind; // 7.0.0+ std::array reserved_2; u32_le hash_offset; u32_le hash_count; From dfd1badc125ca5a4a4fa4587b81f2e51bebb2a07 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Tue, 2 Jun 2020 17:54:10 +0200 Subject: [PATCH 03/12] Address review comments --- src/core/hle/service/ldr/ldr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 252b79d2c7..69caf3aae8 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -59,7 +59,7 @@ struct NRRHeader { u64_le application_id; u32_le size; u8 nrr_kind; // 7.0.0+ - std::array reserved_2; + std::array reserved_2; u32_le hash_offset; u32_le hash_count; u64_le reserved_3; @@ -89,15 +89,15 @@ struct NROHeader { u32_le version; u32_le nro_size; u32_le flags; - // .text, .ro, .data (yuzu previously called it "rw" instead of "data") - std::array segment_headers; + // .text, .ro, .data + std::array segment_headers; u32_le bss_size; u32_le reserved; std::array build_id; u32_le dso_handle_offset; u32_le unused_2; // .apiInfo, .dynstr, .dynsym - std::array segment_headers_2; + std::array segment_headers_2; }; static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size."); From 151a3fe7b327c8adad2bc103029457c353b261c0 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 14 Jun 2020 19:28:39 +0200 Subject: [PATCH 04/12] Attempt to fix crashes in SSBU and refactor IsValidNRO --- src/core/hle/service/ldr/ldr.cpp | 95 ++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 69caf3aae8..5b372b7dbe 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -39,22 +39,27 @@ constexpr ResultCode ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87}; constexpr std::size_t MAXIMUM_LOADED_RO{0x40}; constexpr std::size_t MAXIMUM_MAP_RETRIES{0x200}; -struct Certification { +constexpr std::size_t TEXT_INDEX{0}; +constexpr std::size_t RO_INDEX{1}; +constexpr std::size_t DATA_INDEX{2}; + +struct NRRCertification { u64_le application_id_mask; u64_le application_id_pattern; std::array reserved; std::array public_key; // Also known as modulus std::array signature; }; -static_assert(sizeof(Certification) == 0x220, "Certification has invalid size!"); +static_assert(sizeof(NRRCertification) == 0x220, "Certification has invalid size!"); using SHA256Hash = std::array; +#pragma pack(1) struct NRRHeader { u32_le magic; u32_le certification_signature_key_generation; // 9.0.0+ u64_le reserved; - Certification certification; + NRRCertification certification; std::array signature; u64_le application_id; u32_le size; @@ -63,21 +68,19 @@ struct NRRHeader { u32_le hash_offset; u32_le hash_count; u64_le reserved_3; - - // Must be dynamically allocated because, according to - // SwitchBrew, its size is (0x20 * hash_count) and - // it's impossible to determine the value of hash_count - // (SwitchBrew calls it "NumHash") before runtime, - // therefore it's not possible to calculate a SHA-256 - std::vector NroHashList; }; +#pragma pack() +static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has invalid size!"); +#pragma pack(1) struct SegmentHeader { u32_le memory_offset; u32_le memory_size; }; +#pragma pack() static_assert(sizeof(SegmentHeader) == 0x8, "SegmentHeader has invalid size!"); +#pragma pack(1) struct NROHeader { // Switchbrew calls this "Start" (0x10) u32_le unused; @@ -99,8 +102,10 @@ struct NROHeader { // .apiInfo, .dynstr, .dynsym std::array segment_headers_2; }; +#pragma pack() static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size."); +#pragma pack(1) struct NROInfo { SHA256Hash hash{}; VAddr nro_address{}; @@ -112,6 +117,8 @@ struct NROInfo { std::size_t data_size{}; VAddr src_addr{}; }; +#pragma pack() +static_assert(sizeof(NROInfo) == 0x60, "NROInfo has invalid size."); class DebugMonitor final : public ServiceFramework { public: @@ -369,10 +376,10 @@ public: ResultCode LoadNro(Kernel::Process* process, const NROHeader& nro_header, VAddr nro_addr, VAddr start) const { - const VAddr text_start{start + nro_header.segment_headers[0].memory_offset}; - const VAddr ro_start{start + nro_header.segment_headers[1].memory_offset}; - const VAddr data_start{start + nro_header.segment_headers[2].memory_offset}; - const VAddr bss_start{data_start + nro_header.segment_headers[2].memory_size}; + const VAddr text_start{start + nro_header.segment_headers[TEXT_INDEX].memory_offset}; + const VAddr ro_start{start + nro_header.segment_headers[RO_INDEX].memory_offset}; + const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset}; + const VAddr bss_start{data_start + nro_header.segment_headers[DATA_INDEX].memory_size}; const VAddr bss_end_addr{ Common::AlignUp(bss_start + nro_header.bss_size, Kernel::Memory::PageSize)}; @@ -381,12 +388,12 @@ public: system.Memory().ReadBlock(src_addr, source_data.data(), source_data.size()); system.Memory().WriteBlock(dst_addr, source_data.data(), source_data.size()); }}; - CopyCode(nro_addr + nro_header.segment_headers[0].memory_offset, text_start, - nro_header.segment_headers[0].memory_size); - CopyCode(nro_addr + nro_header.segment_headers[1].memory_offset, ro_start, - nro_header.segment_headers[1].memory_size); - CopyCode(nro_addr + nro_header.segment_headers[2].memory_offset, data_start, - nro_header.segment_headers[2].memory_size); + CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start, + nro_header.segment_headers[TEXT_INDEX].memory_size); + CopyCode(nro_addr + nro_header.segment_headers[RO_INDEX].memory_offset, ro_start, + nro_header.segment_headers[RO_INDEX].memory_size); + CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, + nro_header.segment_headers[DATA_INDEX].memory_size); CASCADE_CODE(process->PageTable().SetCodeMemoryPermission( text_start, ro_start - text_start, Kernel::Memory::MemoryPermission::ReadAndExecute)); @@ -510,9 +517,9 @@ public: // Track the loaded NRO nro.insert_or_assign(*map_result, NROInfo{hash, *map_result, nro_size, bss_address, bss_size, - header.segment_headers[0].memory_size, - header.segment_headers[1].memory_size, - header.segment_headers[2].memory_size, nro_address}); + header.segment_headers[TEXT_INDEX].memory_size, + header.segment_headers[RO_INDEX].memory_size, + header.segment_headers[DATA_INDEX].memory_size, nro_address}); // Invalidate JIT caches for the newly mapped process code system.InvalidateCpuInstructionCaches(); @@ -608,19 +615,35 @@ private: } static bool IsValidNRO(const NROHeader& header, u64 nro_size, u64 bss_size) { - return header.magic == Common::MakeMagic('N', 'R', 'O', '0') && - header.nro_size == nro_size && header.bss_size == bss_size && - header.segment_headers[1].memory_offset == - header.segment_headers[0].memory_offset + - header.segment_headers[0].memory_size && - header.segment_headers[2].memory_offset == - header.segment_headers[1].memory_offset + - header.segment_headers[1].memory_size && - nro_size == header.segment_headers[2].memory_offset + - header.segment_headers[2].memory_size && - Common::Is4KBAligned(header.segment_headers[0].memory_size) && - Common::Is4KBAligned(header.segment_headers[1].memory_size) && - Common::Is4KBAligned(header.segment_headers[2].memory_size); + + const bool valid_magic = header.magic == Common::MakeMagic('N', 'R', 'O', '0'); + + const bool valid_nro_size = header.nro_size == nro_size; + + const bool valid_bss_size = header.bss_size == bss_size; + + const bool valid_ro_offset = header.segment_headers[RO_INDEX].memory_offset == + header.segment_headers[TEXT_INDEX].memory_offset + + header.segment_headers[TEXT_INDEX].memory_size; + + const bool valid_rw_offset = header.segment_headers[DATA_INDEX].memory_offset == + header.segment_headers[RO_INDEX].memory_offset + + header.segment_headers[RO_INDEX].memory_size; + + const bool valid_nro_calculated_size = + nro_size == header.segment_headers[DATA_INDEX].memory_offset + + header.segment_headers[DATA_INDEX].memory_size; + + const bool text_aligned = + Common::Is4KBAligned(header.segment_headers[TEXT_INDEX].memory_size); + + const bool ro_aligned = Common::Is4KBAligned(header.segment_headers[RO_INDEX].memory_size); + + const bool rw_aligned = + Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size); + + return valid_magic && valid_nro_size && valid_bss_size && valid_ro_offset && + valid_rw_offset && valid_nro_calculated_size && text_aligned && ro_aligned && rw_aligned; } Core::System& system; }; From 761d2060493c5c4e1c920659d3b00d8a56164941 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 14 Jun 2020 19:30:08 +0200 Subject: [PATCH 05/12] Make assert strings consistent --- src/core/hle/service/ldr/ldr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 5b372b7dbe..20f268ec02 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -50,7 +50,7 @@ struct NRRCertification { std::array public_key; // Also known as modulus std::array signature; }; -static_assert(sizeof(NRRCertification) == 0x220, "Certification has invalid size!"); +static_assert(sizeof(NRRCertification) == 0x220, "Certification has invalid size."); using SHA256Hash = std::array; @@ -70,7 +70,7 @@ struct NRRHeader { u64_le reserved_3; }; #pragma pack() -static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has invalid size!"); +static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has invalid size."); #pragma pack(1) struct SegmentHeader { @@ -78,7 +78,7 @@ struct SegmentHeader { u32_le memory_size; }; #pragma pack() -static_assert(sizeof(SegmentHeader) == 0x8, "SegmentHeader has invalid size!"); +static_assert(sizeof(SegmentHeader) == 0x8, "SegmentHeader has invalid size."); #pragma pack(1) struct NROHeader { From 1520d7865d0cd0afde690f99de8bf34400671556 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 14 Jun 2020 19:34:58 +0200 Subject: [PATCH 06/12] Clang-format --- src/core/hle/service/ldr/ldr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 20f268ec02..dd0bdde38f 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -643,7 +643,8 @@ private: Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size); return valid_magic && valid_nro_size && valid_bss_size && valid_ro_offset && - valid_rw_offset && valid_nro_calculated_size && text_aligned && ro_aligned && rw_aligned; + valid_rw_offset && valid_nro_calculated_size && text_aligned && ro_aligned && + rw_aligned; } Core::System& system; }; From 198b0fa7901da3a9ab71680351919c41b349e453 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 14 Jun 2020 19:37:44 +0200 Subject: [PATCH 07/12] Use consistent variable names --- src/core/hle/service/ldr/ldr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index dd0bdde38f..d4c6879acc 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -626,7 +626,7 @@ private: header.segment_headers[TEXT_INDEX].memory_offset + header.segment_headers[TEXT_INDEX].memory_size; - const bool valid_rw_offset = header.segment_headers[DATA_INDEX].memory_offset == + const bool valid_data_offset = header.segment_headers[DATA_INDEX].memory_offset == header.segment_headers[RO_INDEX].memory_offset + header.segment_headers[RO_INDEX].memory_size; @@ -639,12 +639,12 @@ private: const bool ro_aligned = Common::Is4KBAligned(header.segment_headers[RO_INDEX].memory_size); - const bool rw_aligned = + const bool data_aligned = Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size); return valid_magic && valid_nro_size && valid_bss_size && valid_ro_offset && - valid_rw_offset && valid_nro_calculated_size && text_aligned && ro_aligned && - rw_aligned; + valid_data_offset && valid_nro_calculated_size && text_aligned && ro_aligned && + data_aligned; } Core::System& system; }; From 39213b1c593828147b4c2c0738e3fc72221c8e6e Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Sun, 14 Jun 2020 19:41:28 +0200 Subject: [PATCH 08/12] Clang-format again --- src/core/hle/service/ldr/ldr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index d4c6879acc..09c17f41f7 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -627,8 +627,8 @@ private: header.segment_headers[TEXT_INDEX].memory_size; const bool valid_data_offset = header.segment_headers[DATA_INDEX].memory_offset == - header.segment_headers[RO_INDEX].memory_offset + - header.segment_headers[RO_INDEX].memory_size; + header.segment_headers[RO_INDEX].memory_offset + + header.segment_headers[RO_INDEX].memory_size; const bool valid_nro_calculated_size = nro_size == header.segment_headers[DATA_INDEX].memory_offset + From 4b71bf654d54210c18e77abda1b3ca20c0e43a63 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Tue, 16 Jun 2020 15:57:02 +0200 Subject: [PATCH 09/12] Update assert string --- src/core/hle/service/ldr/ldr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 09c17f41f7..6daea34089 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -50,7 +50,7 @@ struct NRRCertification { std::array public_key; // Also known as modulus std::array signature; }; -static_assert(sizeof(NRRCertification) == 0x220, "Certification has invalid size."); +static_assert(sizeof(NRRCertification) == 0x220, "NRRCertification has invalid size."); using SHA256Hash = std::array; From c0d61620506ef4d70b1aa60bc9961f08ce9a939f Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Tue, 16 Jun 2020 20:24:58 +0200 Subject: [PATCH 10/12] Revert IsValidNRO refactor but make it more readable --- src/core/hle/service/ldr/ldr.cpp | 39 +++++++++++--------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 6daea34089..ca53a99234 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -615,36 +615,23 @@ private: } static bool IsValidNRO(const NROHeader& header, u64 nro_size, u64 bss_size) { + return header.magic == Common::MakeMagic('N', 'R', 'O', '0') && + header.nro_size == nro_size && header.bss_size == bss_size && - const bool valid_magic = header.magic == Common::MakeMagic('N', 'R', 'O', '0'); + header.segment_headers[RO_INDEX].memory_offset == + header.segment_headers[TEXT_INDEX].memory_offset + + header.segment_headers[TEXT_INDEX].memory_size && - const bool valid_nro_size = header.nro_size == nro_size; + header.segment_headers[DATA_INDEX].memory_offset == + header.segment_headers[RO_INDEX].memory_offset + + header.segment_headers[RO_INDEX].memory_size && - const bool valid_bss_size = header.bss_size == bss_size; + nro_size == header.segment_headers[DATA_INDEX].memory_offset + + header.segment_headers[DATA_INDEX].memory_size && - const bool valid_ro_offset = header.segment_headers[RO_INDEX].memory_offset == - header.segment_headers[TEXT_INDEX].memory_offset + - header.segment_headers[TEXT_INDEX].memory_size; - - const bool valid_data_offset = header.segment_headers[DATA_INDEX].memory_offset == - header.segment_headers[RO_INDEX].memory_offset + - header.segment_headers[RO_INDEX].memory_size; - - const bool valid_nro_calculated_size = - nro_size == header.segment_headers[DATA_INDEX].memory_offset + - header.segment_headers[DATA_INDEX].memory_size; - - const bool text_aligned = - Common::Is4KBAligned(header.segment_headers[TEXT_INDEX].memory_size); - - const bool ro_aligned = Common::Is4KBAligned(header.segment_headers[RO_INDEX].memory_size); - - const bool data_aligned = - Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size); - - return valid_magic && valid_nro_size && valid_bss_size && valid_ro_offset && - valid_data_offset && valid_nro_calculated_size && text_aligned && ro_aligned && - data_aligned; + Common::Is4KBAligned(header.segment_headers[TEXT_INDEX].memory_size) && + Common::Is4KBAligned(header.segment_headers[RO_INDEX].memory_size) && + Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size); } Core::System& system; }; From bd9495c9ab5c1b452c700c54c2bbacf290306741 Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Tue, 16 Jun 2020 20:28:44 +0200 Subject: [PATCH 11/12] Remove unnecessary pragmas --- src/core/hle/service/ldr/ldr.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index ca53a99234..9ce2db1918 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -54,7 +54,6 @@ static_assert(sizeof(NRRCertification) == 0x220, "NRRCertification has invalid s using SHA256Hash = std::array; -#pragma pack(1) struct NRRHeader { u32_le magic; u32_le certification_signature_key_generation; // 9.0.0+ @@ -69,18 +68,14 @@ struct NRRHeader { u32_le hash_count; u64_le reserved_3; }; -#pragma pack() static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has invalid size."); -#pragma pack(1) struct SegmentHeader { u32_le memory_offset; u32_le memory_size; }; -#pragma pack() static_assert(sizeof(SegmentHeader) == 0x8, "SegmentHeader has invalid size."); -#pragma pack(1) struct NROHeader { // Switchbrew calls this "Start" (0x10) u32_le unused; @@ -102,10 +97,8 @@ struct NROHeader { // .apiInfo, .dynstr, .dynsym std::array segment_headers_2; }; -#pragma pack() static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size."); -#pragma pack(1) struct NROInfo { SHA256Hash hash{}; VAddr nro_address{}; @@ -117,7 +110,6 @@ struct NROInfo { std::size_t data_size{}; VAddr src_addr{}; }; -#pragma pack() static_assert(sizeof(NROInfo) == 0x60, "NROInfo has invalid size."); class DebugMonitor final : public ServiceFramework { From 684dfbf20906c4476a7bc28273be9ebd53ab196d Mon Sep 17 00:00:00 2001 From: VolcaEM <63682805+VolcaEM@users.noreply.github.com> Date: Thu, 18 Jun 2020 15:45:47 +0200 Subject: [PATCH 12/12] Move SHA256Hash to its original position It's not needed to have it in its previous position anymore --- src/core/hle/service/ldr/ldr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 9ce2db1918..9f376657c6 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -52,8 +52,6 @@ struct NRRCertification { }; static_assert(sizeof(NRRCertification) == 0x220, "NRRCertification has invalid size."); -using SHA256Hash = std::array; - struct NRRHeader { u32_le magic; u32_le certification_signature_key_generation; // 9.0.0+ @@ -99,6 +97,8 @@ struct NROHeader { }; static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size."); +using SHA256Hash = std::array; + struct NROInfo { SHA256Hash hash{}; VAddr nro_address{};