diff --git a/libraries/libstratosphere/include/stratosphere/dmnt/dmnt_cheat_types.hpp b/libraries/libstratosphere/include/stratosphere/dmnt/dmnt_cheat_types.hpp index c5e0c21ae..d1cd4da24 100644 --- a/libraries/libstratosphere/include/stratosphere/dmnt/dmnt_cheat_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/dmnt/dmnt_cheat_types.hpp @@ -33,7 +33,7 @@ namespace ams::dmnt::cheat { MemoryRegionExtents heap_extents; MemoryRegionExtents alias_extents; MemoryRegionExtents aslr_extents; - u8 main_nso_build_id[0x20]; + u8 main_nso_module_id[0x20]; }; static_assert(util::is_pod::value && sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata definition!"); diff --git a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp index 6bcf05cfa..6a7bf6e81 100644 --- a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp @@ -73,8 +73,12 @@ namespace ams::ldr { } static_assert(sizeof(PinId) == sizeof(u64) && util::is_pod::value, "PinId definition!"); - /* Import ModuleInfo from libnx. */ - using ModuleInfo = ::LoaderModuleInfo; + struct ModuleInfo { + u8 module_id[0x20]; + u64 address; + u64 size; + }; + static_assert(sizeof(ModuleInfo) == 0x30); /* NSO types. */ struct NsoHeader { @@ -123,7 +127,7 @@ namespace ams::ldr { }; SegmentInfo segments[Segment_Count]; }; - u8 build_id[sizeof(ModuleInfo::build_id)]; + u8 module_id[sizeof(ModuleInfo::module_id)]; union { u32 compressed_sizes[Segment_Count]; struct { diff --git a/libraries/libstratosphere/include/stratosphere/ro/impl/ro_debug_monitor_interface.hpp b/libraries/libstratosphere/include/stratosphere/ro/impl/ro_debug_monitor_interface.hpp index 0e151cb58..b4c99061a 100644 --- a/libraries/libstratosphere/include/stratosphere/ro/impl/ro_debug_monitor_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/ro/impl/ro_debug_monitor_interface.hpp @@ -17,9 +17,10 @@ #pragma once #include #include +#include #include #define AMS_RO_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, GetProcessModuleInfo, (sf::Out out_count, const sf::OutArray &out_infos, os::ProcessId process_id), (out_count, out_infos, process_id)) + AMS_SF_METHOD_INFO(C, H, 0, Result, GetProcessModuleInfo, (sf::Out out_count, const sf::OutArray &out_infos, os::ProcessId process_id), (out_count, out_infos, process_id)) AMS_SF_DEFINE_INTERFACE(ams::ro::impl, IDebugMonitorInterface, AMS_RO_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO) diff --git a/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp b/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp index 060625b8f..fb716b028 100644 --- a/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp @@ -27,10 +27,11 @@ namespace ams::ro { NrrKind_Count, }; + static constexpr size_t ModuleIdSize = 0x20; struct ModuleId { - u8 build_id[0x20]; + u8 data[ModuleIdSize]; }; - static_assert(sizeof(ModuleId) == sizeof(LoaderModuleInfo::build_id), "ModuleId definition!"); + static_assert(sizeof(ModuleId) == ModuleIdSize); struct NrrCertification { static constexpr size_t RsaKeySize = 0x100; diff --git a/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp b/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp index 45e470a47..052b6077e 100644 --- a/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp +++ b/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp @@ -43,3 +43,16 @@ \ return ::ams::util::GetReference(s_singleton_storage); \ } + +#define AMS_CONSTINIT_SINGLETON_TRAITS(_CLASSNAME_) \ + private: \ + NON_COPYABLE(_CLASSNAME_); \ + NON_MOVEABLE(_CLASSNAME_); \ + private: \ + constexpr _CLASSNAME_ () = default; \ + public: \ + static _CLASSNAME_ &GetInstance() { \ + /* Declare singleton instance variables. */ \ + static constinit _CLASSNAME_ s_singleton_instance; \ + return s_singleton_instance; \ + } \ No newline at end of file diff --git a/libraries/libstratosphere/source/patcher/patcher_api.cpp b/libraries/libstratosphere/source/patcher/patcher_api.cpp index 1898046b0..3157d4960 100644 --- a/libraries/libstratosphere/source/patcher/patcher_api.cpp +++ b/libraries/libstratosphere/source/patcher/patcher_api.cpp @@ -56,8 +56,8 @@ namespace ams::patcher { /* Read module id from name. */ std::memset(out_module_id, 0, sizeof(*out_module_id)); for (unsigned int name_ofs = 0, id_ofs = 0; name_ofs < name_len - extension_len && id_ofs < sizeof(*out_module_id); id_ofs++) { - out_module_id->build_id[id_ofs] |= ConvertHexNybble(name[name_ofs++]) << 4; - out_module_id->build_id[id_ofs] |= ConvertHexNybble(name[name_ofs++]); + out_module_id->data[id_ofs] |= ConvertHexNybble(name[name_ofs++]) << 4; + out_module_id->data[id_ofs] |= ConvertHexNybble(name[name_ofs++]); } return true; @@ -76,7 +76,7 @@ namespace ams::patcher { bool IsIpsFileForModule(const char *name, const ro::ModuleId *module_id) { const size_t name_len = std::strlen(name); - /* The path must be correct size for a build id (with trailing zeroes optionally trimmed) + ".ips". */ + /* The path must be correct size for a module id (with trailing zeroes optionally trimmed) + ".ips". */ if (!(IpsFileExtensionLength < name_len && name_len <= ModuleIpsPatchLength)) { return false; } diff --git a/libraries/libstratosphere/source/scs/scs_shell.cpp b/libraries/libstratosphere/source/scs/scs_shell.cpp index 01881496b..e645ab11e 100644 --- a/libraries/libstratosphere/source/scs/scs_shell.cpp +++ b/libraries/libstratosphere/source/scs/scs_shell.cpp @@ -330,7 +330,7 @@ namespace ams::scs { Result PrepareToLaunchProgram(ncm::ProgramId program_id, const void *args, size_t args_size) { /* Set the arguments. */ R_TRY_CATCH(ldr::SetProgramArgument(program_id, args, args_size)) { - R_CATCH(ldr::ResultTooManyArguments) { + R_CATCH(ldr::ResultArgumentCountOverflow) { /* There are too many arguments already registered. Flush the arguments queue. */ R_TRY(ldr::FlushArguments()); diff --git a/libraries/libvapours/include/vapours/results/loader_results.hpp b/libraries/libvapours/include/vapours/results/loader_results.hpp index d10a98ec1..691acbd44 100644 --- a/libraries/libvapours/include/vapours/results/loader_results.hpp +++ b/libraries/libvapours/include/vapours/results/loader_results.hpp @@ -21,29 +21,30 @@ namespace ams::ldr { R_DEFINE_NAMESPACE_RESULT_MODULE(9); - R_DEFINE_ERROR_RESULT(TooLongArgument, 1); - R_DEFINE_ERROR_RESULT(TooManyArguments, 2); - R_DEFINE_ERROR_RESULT(TooLargeMeta, 3); - R_DEFINE_ERROR_RESULT(InvalidMeta, 4); - R_DEFINE_ERROR_RESULT(InvalidNso, 5); - R_DEFINE_ERROR_RESULT(InvalidPath, 6); - R_DEFINE_ERROR_RESULT(TooManyProcesses, 7); - R_DEFINE_ERROR_RESULT(NotPinned, 8); - R_DEFINE_ERROR_RESULT(InvalidProgramId, 9); + R_DEFINE_ERROR_RESULT(ArgumentOverflow, 1); + R_DEFINE_ERROR_RESULT(ArgumentCountOverflow, 2); + R_DEFINE_ERROR_RESULT(MetaOverflow, 3); + R_DEFINE_ERROR_RESULT(InvalidMeta, 4); + R_DEFINE_ERROR_RESULT(InvalidNso, 5); + R_DEFINE_ERROR_RESULT(InvalidPath, 6); + R_DEFINE_ERROR_RESULT(MaxProcess, 7); + R_DEFINE_ERROR_RESULT(NotPinned, 8); + R_DEFINE_ERROR_RESULT(InvalidProgramId, 9); R_DEFINE_ERROR_RESULT(InvalidVersion, 10); R_DEFINE_ERROR_RESULT(InvalidAcidSignature, 11); R_DEFINE_ERROR_RESULT(InvalidNcaSignature, 12); - R_DEFINE_ERROR_RESULT(InsufficientAddressSpace, 51); - R_DEFINE_ERROR_RESULT(InvalidNro, 52); - R_DEFINE_ERROR_RESULT(InvalidNrr, 53); - R_DEFINE_ERROR_RESULT(InvalidSignature, 54); - R_DEFINE_ERROR_RESULT(InsufficientNroRegistrations, 55); - R_DEFINE_ERROR_RESULT(InsufficientNrrRegistrations, 56); + R_DEFINE_ERROR_RESULT(OutOfAddressSpace, 51); + R_DEFINE_ERROR_RESULT(InvalidNroImage, 52); + R_DEFINE_ERROR_RESULT(InvalidNrrImage, 53); + R_DEFINE_ERROR_RESULT(NotAuthorized, 54); + R_DEFINE_ERROR_RESULT(MaxModule, 55); + R_DEFINE_ERROR_RESULT(MaxRegistration, 56); R_DEFINE_ERROR_RESULT(NroAlreadyLoaded, 57); R_DEFINE_ERROR_RESULT(InvalidAddress, 81); R_DEFINE_ERROR_RESULT(InvalidSize, 82); + R_DEFINE_ERROR_RESULT(InvalidCurrentMemory, 83); R_DEFINE_ERROR_RESULT(NotLoaded, 84); R_DEFINE_ERROR_RESULT(NotRegistered, 85); R_DEFINE_ERROR_RESULT(InvalidSession, 86); diff --git a/stratosphere/creport/source/creport_modules.cpp b/stratosphere/creport/source/creport_modules.cpp index a9ec94810..6adb970fe 100644 --- a/stratosphere/creport/source/creport_modules.cpp +++ b/stratosphere/creport/source/creport_modules.cpp @@ -54,7 +54,7 @@ namespace ams::creport { if (std::strcmp(m_modules[i].name, "") != 0) { file.WriteFormat(" Name: %s\n", module.name); } - file.DumpMemory(" Build Id: ", module.build_id, sizeof(module.build_id)); + file.DumpMemory(" Module Id: ", module.module_id, sizeof(module.module_id)); } } @@ -104,10 +104,10 @@ namespace ams::creport { module.start_address = mi.base_address; module.end_address = mi.base_address + mi.size; GetModuleName(module.name, module.start_address, module.end_address); - GetModuleBuildId(module.build_id, module.end_address); + GetModuleId(module.module_id, module.end_address); /* Some homebrew won't have a name. Add a fake one for readability. */ if (std::strcmp(module.name, "") == 0) { - util::SNPrintf(module.name, sizeof(module.name), "[%02x%02x%02x%02x]", module.build_id[0], module.build_id[1], module.build_id[2], module.build_id[3]); + util::SNPrintf(module.name, sizeof(module.name), "[%02x%02x%02x%02x]", module.module_id[0], module.module_id[1], module.module_id[2], module.module_id[3]); } } @@ -221,9 +221,9 @@ namespace ams::creport { out_name[ModuleNameLengthMax - 1] = '\x00'; } - void ModuleList::GetModuleBuildId(u8 *out_build_id, uintptr_t ro_start_address) { + void ModuleList::GetModuleId(u8 *out, uintptr_t ro_start_address) { /* Clear output. */ - std::memset(out_build_id, 0, ModuleBuildIdLength); + std::memset(out, 0, ModuleIdSize); /* Verify .rodata is read-only. */ svc::MemoryInfo mi; @@ -238,10 +238,10 @@ namespace ams::creport { return; } - /* Find GNU\x00 to locate start of build id. */ - for (int ofs = read_size - sizeof(GnuSignature) - ModuleBuildIdLength; ofs >= 0; ofs--) { + /* Find GNU\x00 to locate start of module id (GNU build id). */ + for (int ofs = read_size - sizeof(GnuSignature) - ModuleIdSize; ofs >= 0; ofs--) { if (std::memcmp(g_last_rodata_pages + ofs, GnuSignature, sizeof(GnuSignature)) == 0) { - std::memcpy(out_build_id, g_last_rodata_pages + ofs + sizeof(GnuSignature), ModuleBuildIdLength); + std::memcpy(out, g_last_rodata_pages + ofs + sizeof(GnuSignature), ModuleIdSize); break; } } diff --git a/stratosphere/creport/source/creport_modules.hpp b/stratosphere/creport/source/creport_modules.hpp index 13602032b..695313692 100644 --- a/stratosphere/creport/source/creport_modules.hpp +++ b/stratosphere/creport/source/creport_modules.hpp @@ -23,11 +23,11 @@ namespace ams::creport { private: static constexpr size_t ModuleCountMax = 0x60; static constexpr size_t ModuleNameLengthMax = 0x20; - static constexpr size_t ModuleBuildIdLength = 0x20; + static constexpr size_t ModuleIdSize = 0x20; struct ModuleInfo { char name[ModuleNameLengthMax]; - u8 build_id[ModuleBuildIdLength]; + u8 module_id[ModuleIdSize]; u64 start_address; u64 end_address; }; @@ -58,7 +58,7 @@ namespace ams::creport { bool TryFindModule(uintptr_t *out_address, uintptr_t guess); void TryAddModule(uintptr_t guess); void GetModuleName(char *out_name, uintptr_t text_start, uintptr_t ro_start); - void GetModuleBuildId(u8 *out_build_id, uintptr_t ro_start); + void GetModuleId(u8 *out, uintptr_t ro_start); }; } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp index f8c1017f7..b481fb0cb 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp @@ -113,7 +113,7 @@ namespace ams::dmnt::cheat::impl { Result AttachToApplicationProcess(bool on_process_launch); bool ParseCheats(const char *s, size_t len); - bool LoadCheats(const ncm::ProgramId program_id, const u8 *build_id); + bool LoadCheats(const ncm::ProgramId program_id, const u8 *module_id); bool ParseCheatToggles(const char *s, size_t len); bool LoadCheatToggles(const ncm::ProgramId program_id); void SaveCheatToggles(const ncm::ProgramId program_id); @@ -826,16 +826,16 @@ namespace ams::dmnt::cheat::impl { /* Get module information from loader. */ { - LoaderModuleInfo proc_modules[2]; + ldr::ModuleInfo proc_modules[2]; s32 num_modules; /* TODO: ldr::dmnt:: */ - R_ABORT_UNLESS_IF_NEW_PROCESS(ldrDmntGetProcessModuleInfo(static_cast(m_cheat_process_metadata.process_id), proc_modules, util::size(proc_modules), std::addressof(num_modules))); + R_ABORT_UNLESS_IF_NEW_PROCESS(ldrDmntGetProcessModuleInfo(static_cast(m_cheat_process_metadata.process_id), reinterpret_cast(proc_modules), util::size(proc_modules), std::addressof(num_modules))); /* All applications must have two modules. */ /* Only accept one (which means we're attaching to HBL) */ /* if we aren't auto-attaching. */ - const LoaderModuleInfo *proc_module = nullptr; + const ldr::ModuleInfo *proc_module = nullptr; if (num_modules == 2) { proc_module = std::addressof(proc_modules[1]); } else if (num_modules == 1 && !on_process_launch) { @@ -844,13 +844,13 @@ namespace ams::dmnt::cheat::impl { return dmnt::cheat::ResultCheatNotAttached(); } - m_cheat_process_metadata.main_nso_extents.base = proc_module->base_address; + m_cheat_process_metadata.main_nso_extents.base = proc_module->address; m_cheat_process_metadata.main_nso_extents.size = proc_module->size; - std::memcpy(m_cheat_process_metadata.main_nso_build_id, proc_module->build_id, sizeof(m_cheat_process_metadata.main_nso_build_id)); + std::memcpy(m_cheat_process_metadata.main_nso_module_id, proc_module->module_id, sizeof(m_cheat_process_metadata.main_nso_module_id)); } /* Read cheats off the SD. */ - if (!this->LoadCheats(m_cheat_process_metadata.program_id, m_cheat_process_metadata.main_nso_build_id) || + if (!this->LoadCheats(m_cheat_process_metadata.program_id, m_cheat_process_metadata.main_nso_module_id) || !this->LoadCheatToggles(m_cheat_process_metadata.program_id)) { /* If new process launch, require success. */ R_UNLESS(!on_process_launch, dmnt::cheat::ResultCheatNotAttached()); @@ -1059,16 +1059,16 @@ namespace ams::dmnt::cheat::impl { return true; } - bool CheatProcessManager::LoadCheats(const ncm::ProgramId program_id, const u8 *build_id) { + bool CheatProcessManager::LoadCheats(const ncm::ProgramId program_id, const u8 *module_id) { /* Reset existing entries. */ this->ResetAllCheatEntries(); - /* Open the file for program/build_id. */ + /* Open the file for program/module_id. */ fs::FileHandle file; { char path[fs::EntryNameLengthMax + 1]; util::SNPrintf(path, sizeof(path), "sdmc:/atmosphere/contents/%016lx/cheats/%02x%02x%02x%02x%02x%02x%02x%02x.txt", program_id.value, - build_id[0], build_id[1], build_id[2], build_id[3], build_id[4], build_id[5], build_id[6], build_id[7]); + module_id[0], module_id[1], module_id[2], module_id[3], module_id[4], module_id[5], module_id[6], module_id[7]); if (R_FAILED(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Read))) { return false; } diff --git a/stratosphere/loader/source/ldr_arguments.cpp b/stratosphere/loader/source/ldr_arguments.cpp index 4e7cc3c8e..8dd046288 100644 --- a/stratosphere/loader/source/ldr_arguments.cpp +++ b/stratosphere/loader/source/ldr_arguments.cpp @@ -48,13 +48,13 @@ namespace ams::ldr::args { } Result Set(ncm::ProgramId program_id, const void *args, size_t args_size) { - R_UNLESS(args_size < ArgumentSizeMax, ldr::ResultTooLongArgument()); + R_UNLESS(args_size < ArgumentSizeMax, ldr::ResultArgumentOverflow()); ArgumentInfo *arg_info = FindArgumentInfo(program_id); if (arg_info == nullptr) { arg_info = FindFreeArgumentInfo(); } - R_UNLESS(arg_info != nullptr, ldr::ResultTooManyArguments()); + R_UNLESS(arg_info != nullptr, ldr::ResultArgumentCountOverflow()); arg_info->program_id = program_id; arg_info->args_size = args_size; diff --git a/stratosphere/loader/source/ldr_loader_service.cpp b/stratosphere/loader/source/ldr_loader_service.cpp index 5d678b4f0..fddc05bef 100644 --- a/stratosphere/loader/source/ldr_loader_service.cpp +++ b/stratosphere/loader/source/ldr_loader_service.cpp @@ -20,7 +20,6 @@ #include "ldr_process_creation.hpp" #include "ldr_launch_record.hpp" #include "ldr_loader_service.hpp" -#include "ldr_ro_manager.hpp" namespace ams::ldr { @@ -64,7 +63,7 @@ namespace ams::ldr { char path[fs::EntryNameLengthMax]; /* Get location and override status. */ - R_TRY(ldr::ro::GetProgramLocationAndStatus(std::addressof(loc), std::addressof(override_status), id)); + R_TRY(ldr::GetProgramLocationAndOverrideStatusFromPinId(std::addressof(loc), std::addressof(override_status), id)); if (loc.storage_id != static_cast(ncm::StorageId::None)) { R_TRY(ResolveContentPath(path, loc)); @@ -87,11 +86,11 @@ namespace ams::ldr { } Result LoaderService::PinProgram(sf::Out out_id, const ncm::ProgramLocation &loc) { - return ldr::ro::PinProgram(out_id.GetPointer(), loc, cfg::OverrideStatus{}); + return ldr::PinProgram(out_id.GetPointer(), loc, cfg::OverrideStatus{}); } Result LoaderService::UnpinProgram(PinId id) { - return ldr::ro::UnpinProgram(id); + return ldr::UnpinProgram(id); } Result LoaderService::SetProgramArgumentsDeprecated(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size) { @@ -107,8 +106,9 @@ namespace ams::ldr { } Result LoaderService::GetProcessModuleInfo(sf::Out count, const sf::OutPointerArray &out, os::ProcessId process_id) { - R_UNLESS(out.GetSize() <= std::numeric_limits::max(), ldr::ResultInvalidSize()); - return ldr::ro::GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id); + *count = 0; + std::memset(out.GetPointer(), 0, out.GetSize() * sizeof(ldr::ModuleInfo)); + return ldr::GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id); } Result LoaderService::SetEnabledProgramVerification(bool enabled) { @@ -138,7 +138,7 @@ namespace ams::ldr { } Result LoaderService::AtmospherePinProgram(sf::Out out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) { - return ldr::ro::PinProgram(out_id.GetPointer(), loc, override_status); + return ldr::PinProgram(out_id.GetPointer(), loc, override_status); } } diff --git a/stratosphere/loader/source/ldr_meta.cpp b/stratosphere/loader/source/ldr_meta.cpp index d4936570b..c70acde65 100644 --- a/stratosphere/loader/source/ldr_meta.cpp +++ b/stratosphere/loader/source/ldr_meta.cpp @@ -147,7 +147,7 @@ namespace ams::ldr { R_TRY(fs::GetFileSize(std::addressof(npdm_size), file)); /* Read data into cache buffer. */ - R_UNLESS(npdm_size <= static_cast(MetaCacheBufferSize), ldr::ResultTooLargeMeta()); + R_UNLESS(npdm_size <= static_cast(MetaCacheBufferSize), ldr::ResultMetaOverflow()); R_TRY(fs::ReadFile(file, 0, cache->buffer, npdm_size)); } diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index 6764ec093..a014067c6 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -86,7 +86,7 @@ namespace ams::ldr { AMS_ASSUME(ofs < sizeof(module_id)); AMS_ASSUME(str[1] != 0); - module_id.build_id[ofs] = (ParseNybble(str[0]) << 4) | (ParseNybble(str[1]) << 0); + module_id.data[ofs] = (ParseNybble(str[0]) << 4) | (ParseNybble(str[1]) << 0); str += 2; ofs++; @@ -112,21 +112,21 @@ namespace ams::ldr { } /* Apply IPS patches. */ - void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) { + void LocateAndApplyIpsPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size) { if (!EnsureSdCardMounted()) { return; } ro::ModuleId module_id; - std::memcpy(std::addressof(module_id.build_id), build_id, sizeof(module_id.build_id)); + std::memcpy(std::addressof(module_id.data), module_id_data, sizeof(module_id.data)); ams::patcher::LocateAndApplyIpsPatchesToModule(LoaderSdMountName, NsoPatchesDirectory, NsoPatchesProtectedSize, NsoPatchesProtectedOffset, std::addressof(module_id), reinterpret_cast(mapped_nso), mapped_size); } /* Apply embedded patches. */ - void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) { + void ApplyEmbeddedPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size) { /* Make module id. */ ro::ModuleId module_id; - std::memcpy(std::addressof(module_id.build_id), build_id, sizeof(module_id.build_id)); + std::memcpy(std::addressof(module_id.data), module_id_data, sizeof(module_id.data)); if (IsUsb30ForceEnabled()) { for (const auto &patch : Usb30ForceEnablePatches) { diff --git a/stratosphere/loader/source/ldr_patcher.hpp b/stratosphere/loader/source/ldr_patcher.hpp index cbf8c4c14..9aa372168 100644 --- a/stratosphere/loader/source/ldr_patcher.hpp +++ b/stratosphere/loader/source/ldr_patcher.hpp @@ -19,9 +19,9 @@ namespace ams::ldr { /* Apply IPS patches. */ - void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size); + void LocateAndApplyIpsPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size); /* Apply embedded patches. */ - void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size); + void ApplyEmbeddedPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size); } \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index a2a40c72d..b1bb41583 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -591,10 +591,10 @@ namespace ams::ldr { std::memset(reinterpret_cast(map_address + rw_end), 0, nso_header->bss_size); /* Apply embedded patches. */ - ApplyEmbeddedPatchesToModule(nso_header->build_id, map_address, nso_size); + ApplyEmbeddedPatchesToModule(nso_header->module_id, map_address, nso_size); /* Apply IPS patches. */ - LocateAndApplyIpsPatchesToModule(nso_header->build_id, map_address, nso_size); + LocateAndApplyIpsPatchesToModule(nso_header->module_id, map_address, nso_size); } /* Set permissions. */ @@ -683,24 +683,32 @@ namespace ams::ldr { ProcessInfo info; R_TRY(CreateProcessImpl(std::addressof(info), std::addressof(meta), nso_headers, has_nso, arg_info, flags, reslimit_h)); - /* Ensure we close the process handle, if we fail. */ - ON_SCOPE_EXIT { os::CloseNativeHandle(info.process_handle); }; - /* Load NSOs into process memory. */ - R_TRY(LoadNsosIntoProcessMemory(std::addressof(info), nso_headers, has_nso, arg_info)); + { + /* Ensure we close the process handle, if we fail. */ + auto process_guard = SCOPE_GUARD { os::CloseNativeHandle(info.process_handle); }; - /* Register NSOs with ro manager. */ + /* Load all NSOs. */ + R_TRY(LoadNsosIntoProcessMemory(std::addressof(info), nso_headers, has_nso, arg_info)); + + /* We don't need to close the process handle, since we succeeded. */ + process_guard.Cancel(); + } + + /* Register NSOs with the RoManager. */ { /* Nintendo doesn't validate this get, but we do. */ os::ProcessId process_id = os::GetProcessId(info.process_handle); /* Register new process. */ - ldr::ro::RegisterProcess(pin_id, process_id, loc.program_id); + /* NOTE: Nintendo uses meta->aci->program_id, not loc.program_id. Should we? */ + const auto as_type = GetAddressSpaceType(std::addressof(meta)); + RoManager::GetInstance().RegisterProcess(pin_id, process_id, loc.program_id, as_type == Npdm::AddressSpaceType_64Bit || as_type == Npdm::AddressSpaceType_64BitDeprecated); /* Register all NSOs. */ for (size_t i = 0; i < Nso_Count; i++) { if (has_nso[i]) { - ldr::ro::RegisterModule(pin_id, nso_headers[i].build_id, info.nso_address[i], info.nso_size[i]); + RoManager::GetInstance().AddNso(pin_id, nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]); } } } @@ -719,7 +727,6 @@ namespace ams::ldr { /* Move the process handle to output. */ *out = info.process_handle; - info.process_handle = os::InvalidNativeHandle; } return ResultSuccess(); @@ -741,4 +748,24 @@ namespace ams::ldr { return GetProgramInfoFromMeta(out, std::addressof(meta)); } + Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) { + R_UNLESS(RoManager::GetInstance().Allocate(out_id, loc, override_status), ldr::ResultMaxProcess()); + return ResultSuccess(); + } + + Result UnpinProgram(PinId id) { + R_UNLESS(RoManager::GetInstance().Free(id), ldr::ResultNotPinned()); + return ResultSuccess(); + } + + Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) { + R_UNLESS(RoManager::GetInstance().GetProcessModuleInfo(out_count, out, max_out_count, process_id), ldr::ResultNotPinned()); + return ResultSuccess(); + } + + Result GetProgramLocationAndOverrideStatusFromPinId(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id) { + R_UNLESS(RoManager::GetInstance().GetProgramLocationAndStatus(out, out_status, pin_id), ldr::ResultNotPinned()); + return ResultSuccess(); + } + } diff --git a/stratosphere/loader/source/ldr_process_creation.hpp b/stratosphere/loader/source/ldr_process_creation.hpp index 6e2082c62..e4924e628 100644 --- a/stratosphere/loader/source/ldr_process_creation.hpp +++ b/stratosphere/loader/source/ldr_process_creation.hpp @@ -22,4 +22,11 @@ namespace ams::ldr { Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, os::NativeHandle reslimit_h); Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc); + Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status); + Result UnpinProgram(PinId id); + + Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id); + + Result GetProgramLocationAndOverrideStatusFromPinId(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id); + } diff --git a/stratosphere/loader/source/ldr_ro_manager.cpp b/stratosphere/loader/source/ldr_ro_manager.cpp index ed9833b41..35ec0045f 100644 --- a/stratosphere/loader/source/ldr_ro_manager.cpp +++ b/stratosphere/loader/source/ldr_ro_manager.cpp @@ -16,147 +16,166 @@ #include #include "ldr_ro_manager.hpp" -namespace ams::ldr::ro { +namespace ams::ldr { - namespace { - - /* Convenience definitions. */ - constexpr PinId InvalidPinId = {}; - constexpr size_t ProcessCountMax = 0x40; - constexpr size_t ModuleCountMax = 0x20; - - /* Types. */ - struct ModuleInfo { - ldr::ModuleInfo info; - bool in_use; - }; - - struct ProcessInfo { - PinId pin_id; - os::ProcessId process_id; - ncm::ProgramId program_id; - cfg::OverrideStatus override_status; - ncm::ProgramLocation loc; - ModuleInfo modules[ModuleCountMax]; - bool in_use; - }; - - /* Globals. */ - ProcessInfo g_process_infos[ProcessCountMax]; - u64 g_cur_pin_id = 1; - - /* Helpers. */ - ProcessInfo *GetProcessInfo(PinId pin_id) { - for (size_t i = 0; i < ProcessCountMax; i++) { - ProcessInfo *info = g_process_infos + i; - if (info->in_use && info->pin_id == pin_id) { - return info; - } - } - return nullptr; - } - - ProcessInfo *GetProcessInfo(os::ProcessId process_id) { - for (size_t i = 0; i < ProcessCountMax; i++) { - ProcessInfo *info = g_process_infos + i; - if (info->in_use && info->process_id == process_id) { - return info; - } - } - return nullptr; - } - - ProcessInfo *GetFreeProcessInfo() { - for (size_t i = 0; i < ProcessCountMax; i++) { - ProcessInfo *info = g_process_infos + i; - if (!info->in_use) { - return info; - } - } - return nullptr; - } - - } - - /* RO Manager API. */ - Result PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) { + bool RoManager::Allocate(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) { + /* Ensure that output pin id is set. */ *out = InvalidPinId; - ProcessInfo *info = GetFreeProcessInfo(); - R_UNLESS(info != nullptr, ldr::ResultTooManyProcesses()); - std::memset(info, 0, sizeof(*info)); - info->pin_id = { g_cur_pin_id++ }; - info->loc = loc; - info->override_status = status; - info->in_use = true; - *out = info->pin_id; - return ResultSuccess(); - } - - Result UnpinProgram(PinId id) { - ProcessInfo *info = GetProcessInfo(id); - R_UNLESS(info != nullptr, ldr::ResultNotPinned()); - - info->in_use = false; - return ResultSuccess(); - } - - - Result GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId id) { - ProcessInfo *info = GetProcessInfo(id); - R_UNLESS(info != nullptr, ldr::ResultNotPinned()); - - *out = info->loc; - *out_status = info->override_status; - return ResultSuccess(); - } - - Result RegisterProcess(PinId id, os::ProcessId process_id, ncm::ProgramId program_id) { - ProcessInfo *info = GetProcessInfo(id); - R_UNLESS(info != nullptr, ldr::ResultNotPinned()); - - info->program_id = program_id; - info->process_id = process_id; - return ResultSuccess(); - } - - Result RegisterModule(PinId id, const u8 *build_id, uintptr_t address, size_t size) { - ProcessInfo *info = GetProcessInfo(id); - R_UNLESS(info != nullptr, ldr::ResultNotPinned()); - - /* Nintendo doesn't actually care about successful allocation. */ - for (size_t i = 0; i < ModuleCountMax; i++) { - ModuleInfo *module = info->modules + i; - if (module->in_use) { - continue; - } - - std::memcpy(module->info.build_id, build_id, sizeof(module->info.build_id)); - module->info.base_address = address; - module->info.size = size; - module->in_use = true; - break; + /* Allocate a process info. */ + auto *found = this->AllocateProcessInfo(); + if (found == nullptr) { + return false; } - return ResultSuccess(); + /* Setup the process info. */ + std::memset(found, 0, sizeof(*found)); + found->pin_id = { ++m_pin_id }; + found->program_location = loc; + found->override_status = status; + found->in_use = true; + + /* Set the output pin id. */ + *out = found->pin_id; + return true; } - Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) { - const ProcessInfo *info = GetProcessInfo(process_id); - R_UNLESS(info != nullptr, ldr::ResultNotPinned()); + bool RoManager::Free(PinId pin_id) { + /* Find the process. */ + auto *found = this->FindProcessInfo(pin_id); + if (found == nullptr) { + return false; + } + /* Set the process as not in use. */ + found->in_use = false; + + /* Set all the process's nsos as not in use. */ + for (auto i = 0; i < NsoCount; ++i) { + found->nso_infos[i].in_use = false; + } + + return true; + } + + void RoManager::RegisterProcess(PinId pin_id, os::ProcessId process_id, ncm::ProgramId program_id, bool is_64_bit_address_space) { + /* Find the process. */ + auto *found = this->FindProcessInfo(pin_id); + if (found == nullptr) { + return; + } + + /* Set the process id and program id. */ + found->process_id = process_id; + found->program_id = program_id; + AMS_UNUSED(is_64_bit_address_space); + } + + bool RoManager::GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id) { + /* Find the process. */ + auto *found = this->FindProcessInfo(pin_id); + if (found == nullptr) { + return false; + } + + /* Set the output location/status. */ + *out = found->program_location; + *out_status = found->override_status; + return true; + } + + void RoManager::AddNso(PinId pin_id, const u8 *module_id, u64 address, u64 size) { + /* Find the process. */ + auto *found = this->FindProcessInfo(pin_id); + if (found == nullptr) { + return; + } + + /* Allocate an nso. */ + auto *info = this->AllocateNsoInfo(found); + if (info == nullptr) { + return; + } + + /* Copy the information into the nso info. */ + std::memcpy(info->module_info.module_id, module_id, sizeof(info->module_info.module_id)); + info->module_info.address = address; + info->module_info.size = size; + info->in_use = true; + } + + bool RoManager::GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) { + /* Find the process. */ + auto *found = this->FindProcessInfo(process_id); + if (found == nullptr) { + return false; + } + + /* Copy allocated nso module infos. */ size_t count = 0; - for (size_t i = 0; i < ModuleCountMax && count < max_out_count; i++) { - const ModuleInfo *module = info->modules + i; - if (!module->in_use) { + for (auto i = 0; i < NsoCount && count < max_out_count; ++i) { + /* Skip unallocated nsos. */ + if (!found->nso_infos[i].in_use) { continue; } - out[count++] = module->info; + /* Copy out the module info. */ + out[count++] = found->nso_infos[i].module_info; } - *out_count = static_cast(count); - return ResultSuccess(); + /* Set the output count. */ + *out_count = count; + return true; + } + + RoManager::ProcessInfo *RoManager::AllocateProcessInfo() { + for (auto i = 0; i < ProcessCount; ++i) { + if (!m_processes[i].in_use) { + return m_processes + i; + } + } + + return nullptr; + } + + RoManager::ProcessInfo *RoManager::FindProcessInfo(PinId pin_id) { + for (auto i = 0; i < ProcessCount; ++i) { + if (m_processes[i].in_use && m_processes[i].pin_id == pin_id) { + return m_processes + i; + } + } + + return nullptr; + } + + RoManager::ProcessInfo *RoManager::FindProcessInfo(os::ProcessId process_id) { + for (auto i = 0; i < ProcessCount; ++i) { + if (m_processes[i].in_use && m_processes[i].process_id == process_id) { + return m_processes + i; + } + } + + return nullptr; + } + + RoManager::ProcessInfo *RoManager::FindProcessInfo(ncm::ProgramId program_id) { + for (auto i = 0; i < ProcessCount; ++i) { + if (m_processes[i].in_use && m_processes[i].program_id == program_id) { + return m_processes + i; + } + } + + return nullptr; + } + + RoManager::NsoInfo *RoManager::AllocateNsoInfo(ProcessInfo *info) { + for (auto i = 0; i < NsoCount; ++i) { + if (!info->nso_infos[i].in_use) { + return info->nso_infos + i; + } + } + + return nullptr; } } diff --git a/stratosphere/loader/source/ldr_ro_manager.hpp b/stratosphere/loader/source/ldr_ro_manager.hpp index e3b694870..4d9e99f41 100644 --- a/stratosphere/loader/source/ldr_ro_manager.hpp +++ b/stratosphere/loader/source/ldr_ro_manager.hpp @@ -16,14 +16,50 @@ #pragma once #include -namespace ams::ldr::ro { +namespace ams::ldr { - /* RO Manager API. */ - Result PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status); - Result UnpinProgram(PinId id); - Result GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId id); - Result RegisterProcess(PinId id, os::ProcessId process_id, ncm::ProgramId program_id); - Result RegisterModule(PinId id, const u8 *build_id, uintptr_t address, size_t size); - Result GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id); + class RoManager { + AMS_CONSTINIT_SINGLETON_TRAITS(RoManager); + public: + static constexpr PinId InvalidPinId = {}; + static constexpr int ProcessCount = 0x40; + static constexpr int NsoCount = 0x20; + private: + struct NsoInfo { + bool in_use; + ldr::ModuleInfo module_info; + }; + + struct ProcessInfo { + bool in_use; + PinId pin_id; + os::ProcessId process_id; + ncm::ProgramId program_id; + cfg::OverrideStatus override_status; + ncm::ProgramLocation program_location; + NsoInfo nso_infos[NsoCount]; + }; + private: + ProcessInfo m_processes[ProcessCount]; + u64 m_pin_id; + public: + bool Allocate(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status); + bool Free(PinId pin_id); + + void RegisterProcess(PinId pin_id, os::ProcessId process_id, ncm::ProgramId program_id, bool is_64_bit_address_space); + + bool GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id); + + void AddNso(PinId pin_id, const u8 *module_id, u64 address, u64 size); + + bool GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id); + private: + ProcessInfo *AllocateProcessInfo(); + ProcessInfo *FindProcessInfo(PinId pin_id); + ProcessInfo *FindProcessInfo(os::ProcessId process_id); + ProcessInfo *FindProcessInfo(ncm::ProgramId program_id); + + NsoInfo *AllocateNsoInfo(ProcessInfo *info); + }; } diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp index 3604c51bc..fd5a9a57a 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.cpp +++ b/stratosphere/ro/source/impl/ro_service_impl.cpp @@ -320,7 +320,7 @@ namespace ams::ro::impl { m_nro_in_use[index] = in_use; } - void GetProcessModuleInfo(u32 *out_count, LoaderModuleInfo *out_infos, size_t max_out_count) const { + void GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out_infos, size_t max_out_count) const { size_t count = 0; for (size_t i = 0; i < MaxNroInfos && count < max_out_count; i++) { @@ -331,10 +331,11 @@ namespace ams::ro::impl { const NroInfo *nro_info = m_nro_infos + i; /* Just copy out the info. */ - LoaderModuleInfo *out_info = std::addressof(out_infos[count++]); - memcpy(out_info->build_id, std::addressof(nro_info->module_id), sizeof(nro_info->module_id)); - out_info->base_address = nro_info->base_address; - out_info->size = nro_info->nro_heap_size + nro_info->bss_heap_size; + auto &out_info = out_infos[count++]; + + std::memcpy(out_info.module_id, nro_info->module_id.data, sizeof(out_info.module_id)); + out_info.address = nro_info->base_address; + out_info.size = nro_info->nro_heap_size + nro_info->bss_heap_size; } *out_count = static_cast(count); @@ -597,7 +598,7 @@ namespace ams::ro::impl { } /* Debug service implementations. */ - Result GetProcessModuleInfo(u32 *out_count, LoaderModuleInfo *out_infos, size_t max_out_count, os::ProcessId process_id) { + Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out_infos, size_t max_out_count, os::ProcessId process_id) { if (const ProcessContext *context = GetContextByProcessId(process_id); context != nullptr) { context->GetProcessModuleInfo(out_count, out_infos, max_out_count); } diff --git a/stratosphere/ro/source/impl/ro_service_impl.hpp b/stratosphere/ro/source/impl/ro_service_impl.hpp index 090a88834..ffc92f02d 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.hpp +++ b/stratosphere/ro/source/impl/ro_service_impl.hpp @@ -41,6 +41,6 @@ namespace ams::ro::impl { Result UnmapManualLoadModuleMemory(size_t context_id, u64 nro_address); /* Debug service implementations. */ - Result GetProcessModuleInfo(u32 *out_count, LoaderModuleInfo *out_infos, size_t max_out_count, os::ProcessId process_id); + Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out_infos, size_t max_out_count, os::ProcessId process_id); } diff --git a/stratosphere/ro/source/ro_debug_monitor_service.cpp b/stratosphere/ro/source/ro_debug_monitor_service.cpp index 7f2bc42e4..a3ff79abf 100644 --- a/stratosphere/ro/source/ro_debug_monitor_service.cpp +++ b/stratosphere/ro/source/ro_debug_monitor_service.cpp @@ -19,7 +19,7 @@ namespace ams::ro { - Result DebugMonitorService::GetProcessModuleInfo(sf::Out out_count, const sf::OutArray &out_infos, os::ProcessId process_id) { + Result DebugMonitorService::GetProcessModuleInfo(sf::Out out_count, const sf::OutArray &out_infos, os::ProcessId process_id) { R_UNLESS(out_infos.GetSize() <= std::numeric_limits::max(), ro::ResultInvalidSize()); return impl::GetProcessModuleInfo(out_count.GetPointer(), out_infos.GetPointer(), out_infos.GetSize(), process_id); } diff --git a/stratosphere/ro/source/ro_debug_monitor_service.hpp b/stratosphere/ro/source/ro_debug_monitor_service.hpp index 5bb9f70f5..94df39e14 100644 --- a/stratosphere/ro/source/ro_debug_monitor_service.hpp +++ b/stratosphere/ro/source/ro_debug_monitor_service.hpp @@ -20,7 +20,7 @@ namespace ams::ro { class DebugMonitorService { public: - Result GetProcessModuleInfo(sf::Out out_count, const sf::OutArray &out_infos, os::ProcessId process_id); + Result GetProcessModuleInfo(sf::Out out_count, const sf::OutArray &out_infos, os::ProcessId process_id); }; static_assert(ro::impl::IsIDebugMonitorInterface);