mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
loader: refactor ro manager/improve accuracy
This commit is contained in:
parent
d8a36e39f2
commit
d9dc04318d
24 changed files with 328 additions and 218 deletions
|
@ -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<CheatProcessMetadata>::value && sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata definition!");
|
||||
|
|
|
@ -73,8 +73,12 @@ namespace ams::ldr {
|
|||
}
|
||||
static_assert(sizeof(PinId) == sizeof(u64) && util::is_pod<PinId>::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 {
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/ro/ro_types.hpp>
|
||||
#include <stratosphere/ldr/ldr_types.hpp>
|
||||
#include <stratosphere/sf.hpp>
|
||||
|
||||
#define AMS_RO_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProcessModuleInfo, (sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id), (out_count, out_infos, process_id))
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProcessModuleInfo, (sf::Out<u32> out_count, const sf::OutArray<ldr::ModuleInfo> &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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; \
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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(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(TooManyProcesses, 7);
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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<u64>(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<u64>(m_cheat_process_metadata.process_id), reinterpret_cast<LoaderModuleInfo *>(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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<u8>(ncm::StorageId::None)) {
|
||||
R_TRY(ResolveContentPath(path, loc));
|
||||
|
@ -87,11 +86,11 @@ namespace ams::ldr {
|
|||
}
|
||||
|
||||
Result LoaderService::PinProgram(sf::Out<PinId> 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<u32> count, const sf::OutPointerArray<ModuleInfo> &out, os::ProcessId process_id) {
|
||||
R_UNLESS(out.GetSize() <= std::numeric_limits<s32>::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<PinId> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<s64>(MetaCacheBufferSize), ldr::ResultTooLargeMeta());
|
||||
R_UNLESS(npdm_size <= static_cast<s64>(MetaCacheBufferSize), ldr::ResultMetaOverflow());
|
||||
R_TRY(fs::ReadFile(file, 0, cache->buffer, npdm_size));
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u8 *>(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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -591,10 +591,10 @@ namespace ams::ldr {
|
|||
std::memset(reinterpret_cast<void *>(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. */
|
||||
{
|
||||
/* Ensure we close the process handle, if we fail. */
|
||||
auto process_guard = SCOPE_GUARD { os::CloseNativeHandle(info.process_handle); };
|
||||
|
||||
/* Load all NSOs. */
|
||||
R_TRY(LoadNsosIntoProcessMemory(std::addressof(info), nso_headers, has_nso, arg_info));
|
||||
|
||||
/* Register NSOs with ro manager. */
|
||||
/* 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -16,147 +16,166 @@
|
|||
#include <stratosphere.hpp>
|
||||
#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;
|
||||
/* Allocate a process info. */
|
||||
auto *found = this->AllocateProcessInfo();
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
*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();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
/* 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<u32>(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,14 +16,50 @@
|
|||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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<u32>(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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
namespace ams::ro {
|
||||
|
||||
Result DebugMonitorService::GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id) {
|
||||
Result DebugMonitorService::GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<ldr::ModuleInfo> &out_infos, os::ProcessId process_id) {
|
||||
R_UNLESS(out_infos.GetSize() <= std::numeric_limits<s32>::max(), ro::ResultInvalidSize());
|
||||
return impl::GetProcessModuleInfo(out_count.GetPointer(), out_infos.GetPointer(), out_infos.GetSize(), process_id);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ams::ro {
|
|||
|
||||
class DebugMonitorService {
|
||||
public:
|
||||
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id);
|
||||
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<ldr::ModuleInfo> &out_infos, os::ProcessId process_id);
|
||||
};
|
||||
static_assert(ro::impl::IsIDebugMonitorInterface<DebugMonitorService>);
|
||||
|
||||
|
|
Loading…
Reference in a new issue