From 94e62a7b1b253f0cfc07ca53c6d0ec3f9599359c Mon Sep 17 00:00:00 2001 From: Alula Date: Wed, 24 Jun 2026 20:54:42 +0200 Subject: [PATCH] loader: add non-release build debug logging --- .../loader/source/ldr_process_creation.cpp | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 51e69ebdd..f4dc57862 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -219,7 +219,7 @@ namespace ams::ldr { /* Read NSO header. */ size_t read_size; R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, g_nso_headers + ctx.nso_count, sizeof(NsoHeader))); - R_UNLESS(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso()); + R_UNLESS_LOG(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso(), "[ldr] NSO header truncated!\n"); /* Note nso is present. */ switch (i) { @@ -258,7 +258,7 @@ namespace ams::ldr { Result CheckAutoLoad(const AutoLoadModuleContext &ctx, u32 acid_flags) { /* We must always have a main. */ - R_UNLESS(ctx.ali.has_main, ldr::ResultInvalidNso()); + R_UNLESS_LOG(ctx.ali.has_main, ldr::ResultInvalidNso(), "[ldr] Missing main!\n"); /* Validate flags and extents for all present NSOs. */ for (int i = 0; i < ctx.nso_count; ++i) { @@ -266,11 +266,11 @@ namespace ams::ldr { /* All NSOs must not be --X. */ /* This is "probably" not checked on Ounce? */ - R_UNLESS((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso()); + R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] --x not allowed!\n", i); /* Zstd compression only allowed on main, and only when both rtld+sdk are present. */ if (i != ctx.main_nso_idx || ctx.rtld_idx < 0 || ctx.sdk_nso_idx < 0) { - R_UNLESS((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso()); + R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] zbic not allowed!\n", i); } /* NSOs must have page-aligned segments. */ @@ -293,13 +293,13 @@ namespace ams::ldr { const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0; if (ctx.ali.has_rtld || ctx.ali.has_sdk) { /* If we have sdk we must have rtld. */ - R_UNLESS(ctx.ali.has_rtld, ldr::ResultInvalidNso()); + R_UNLESS_LOG(ctx.ali.has_rtld, ldr::ResultInvalidNso(), "[ldr] Missing rtld!\n"); /* If we have rtld, we must not have browser core dll. */ - R_UNLESS(!has_browser_dll, ldr::ResultInvalidNso()); + R_UNLESS_LOG(!has_browser_dll, ldr::ResultInvalidNso(), "[ldr] BrowserCoreDll must not be present!\n"); } else { /* We must not have both subsdk and browser dll. */ - R_UNLESS(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso()); + R_UNLESS_LOG(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso(), "[ldr] Can't have both subsdk and BrowserCoreDll!\n"); } R_SUCCEED(); @@ -384,6 +384,8 @@ namespace ams::ldr { /* If the signature check fails, we need to check if this is allowable. */ if (!is_signature_valid) { + AMS_LOG("[ldr] invalid signature!\n"); + /* We have to enforce signature checks on prod and when we have a signature to check on dev. */ R_UNLESS(IsDevelopmentForAcidProductionCheck(), ldr::ResultInvalidNcaSignature()); R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature()); @@ -634,10 +636,13 @@ namespace ams::ldr { R_SUCCEED(); } - Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zstd, uintptr_t map_base, uintptr_t map_end) { + Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zbic, uintptr_t map_base, uintptr_t map_end) { /* Select read size based on compression. */ size_t file_size = is_compressed ? compressed_size : segment_size; + AMS_LOG("[ldr] Loading segment @ 0x%016lx: compressed=%d, file_size=0x%08lx, compressed_size=0x%08lx, segment_size=0x%08lx\n", + map_base, is_compressed, file_size, compressed_size, segment_size); + /* Validate size. */ R_UNLESS(file_size <= segment_size, ldr::ResultInvalidNso()); R_UNLESS(file_size <= std::numeric_limits::max(), ldr::ResultInvalidNso()); @@ -647,19 +652,19 @@ namespace ams::ldr { uintptr_t load_address = is_compressed ? map_end - compressed_size : map_base; size_t read_size; R_TRY(fs::ReadFile(std::addressof(read_size), file, file_offset, reinterpret_cast(load_address), file_size)); - R_UNLESS(read_size == file_size, ldr::ResultInvalidNso()); + R_UNLESS_LOG(read_size == file_size, ldr::ResultInvalidNso(), "[ldr] Couldn't read segment from file!\n"); /* Uncompress if necessary. */ R_SUCCEED_IF(!is_compressed); auto compressed_data_buf = reinterpret_cast(load_address); - if (is_zstd) { + if (is_zbic) { bool decompressed = util::DecompressZbicForLoader(reinterpret_cast(g_zstd_dctx_workspace), sizeof(g_zstd_dctx_workspace), reinterpret_cast(map_base), static_cast(map_end - map_base), segment_size, compressed_data_buf, file_size); - R_UNLESS(decompressed, ldr::ResultInvalidNso()); + R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with zbic!\n"); } else { bool decompressed = (util::DecompressLZ4(reinterpret_cast(map_base), segment_size, compressed_data_buf, file_size) == static_cast(segment_size)); - R_UNLESS(decompressed, ldr::ResultInvalidNso()); + R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with lz4!\n"); } R_SUCCEED(); @@ -674,12 +679,12 @@ namespace ams::ldr { crypto::GenerateSha256(hash, sizeof(hash), reinterpret_cast(map_address + nso_header->segments[segment].dst_offset), nso_header->segments[segment].size); - R_UNLESS(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso()); + R_UNLESS_LOG(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso(), "[ldr] Invalid segment hash!\n"); R_SUCCEED(); } Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size, size_t map_size) { - const bool is_zstd = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0; + const bool is_zbic = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0; /* Map and read data from file. */ { @@ -693,11 +698,11 @@ namespace ams::ldr { /* Load NSO segments. */ R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Text].file_offset, nso_header->text_compressed_size, nso_header->text_size, - (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zstd, map_address + nso_header->text_dst_offset, map_end)); + (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zbic, map_address + nso_header->text_dst_offset, map_end)); R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Ro].file_offset, nso_header->ro_compressed_size, nso_header->ro_size, - (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zstd, map_address + nso_header->ro_dst_offset, map_end)); + (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zbic, map_address + nso_header->ro_dst_offset, map_end)); R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Rw].file_offset, nso_header->rw_compressed_size, nso_header->rw_size, - (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zstd, map_address + nso_header->rw_dst_offset, map_end)); + (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zbic, map_address + nso_header->rw_dst_offset, map_end)); /* Clear unused space to zero. */ const size_t text_end = static_cast(nso_header->text_dst_offset) + static_cast(nso_header->text_size); @@ -743,14 +748,15 @@ namespace ams::ldr { for (int i = 0; i < ctx.nso_count; i++) { const NsoIndex nso_idx = static_cast(ctx.ali.nso_indices[i]); + const bool is_zbic = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0; + const size_t map_size = is_zbic ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i]; + + AMS_LOG("[ldr] module[%d]: idx=%d, path='%s', zbic=%d\n", i, (int)nso_idx, GetNsoPath(nso_idx), is_zbic); fs::FileHandle file; R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(nso_idx), fs::OpenMode_Read)); ON_SCOPE_EXIT { fs::CloseFile(file); }; - const bool is_zstd = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0; - const size_t map_size = is_zstd ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i]; - R_TRY(LoadAutoLoadModule(process_info->process_handle, file, ctx.headers + i, process_info->nso_address[i], process_info->nso_size[i], map_size)); }