From 1d73bd0a12687355b29fe9a852551f4bb8c16f9b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 19:13:55 -0600 Subject: [PATCH] Loader: Start work on LoadNRR, Add AutoCloseMap --- stratosphere/loader/source/ldr_map.hpp | 43 +++++++++++++++++++ stratosphere/loader/source/ldr_nso.cpp | 31 ++++--------- .../loader/source/ldr_registration.cpp | 20 +++++++++ .../loader/source/ldr_registration.hpp | 5 ++- stratosphere/loader/source/ldr_ro_service.cpp | 32 +++++++++++++- 5 files changed, 105 insertions(+), 26 deletions(-) diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index 301b8f4ac..f546bf77b 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -25,4 +25,47 @@ class MapUtils { static Result MapCodeMemoryForProcessDeprecated(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address); static Result MapCodeMemoryForProcessModern(Handle process_h, u64 base_address, u64 size, u64 *out_code_memory_address); static Result MapCodeMemoryForProcess(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address); +}; + +class AutoCloseMap { + private: + void *mapped_address; + u64 base_address; + u64 size; + Handle process_handle; + public: + AutoCloseMap() : mapped_address(0), base_address(0), size(0), process_handle(0) { }; + ~AutoCloseMap() { + Close(); + } + + void *GetMappedAddress() { + return this->mapped_address; + } + + Result Open(Handle process_h, u64 address, u64 size) { + Result rc; + u64 try_address; + if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) { + return rc; + } + + if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, process_h, try_address, size)))) { + return rc; + } + + this->mapped_address = (void *)try_address; + this->process_handle = process_h; + this->base_address = address; + this->size = size; + return 0; + } + + void Close() { + if (this->mapped_address) { + if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) { + /* TODO: panic(). */ + } + } + } }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 9011725c7..4e70d75b9 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -224,17 +224,13 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo Result rc = 0xA09; for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (g_nso_present[i]) { - u64 map_addr = 0; - if (R_FAILED((rc = MapUtils::LocateSpaceForMap(&map_addr, extents->nso_sizes[i])))) { - return rc; - } - - u8 *map_base = (u8 *)map_addr; - - if (R_FAILED((rc = svcMapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { + AutoCloseMap nso_map; + if (R_FAILED((rc = nso_map.Open(process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { return rc; } + u8 *map_base = (u8 *)nso_map.GetMappedAddress(); + FILE *f_nso = OpenNso(i, title_id); if (f_nso == NULL) { /* Is there a better error to return here? */ @@ -243,7 +239,6 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo for (unsigned int seg = 0; seg < 3; seg++) { if (R_FAILED((rc = LoadNsoSegment(i, seg, f_nso, map_base, map_base + extents->nso_sizes[i])))) { fclose(f_nso); - svcUnmapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i]); return rc; } } @@ -262,9 +257,7 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo u64 bss_base = rw_base + g_nso_headers[i].segments[2].decomp_size, bss_size = g_nso_headers[i].segments[2].align_or_total_size; std::fill(map_base + bss_base, map_base + bss_base + bss_size, 0); - if (R_FAILED((rc = svcUnmapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { - return rc; - } + nso_map.Close(); for (unsigned int seg = 0; seg < 3; seg++) { u64 size = g_nso_headers[i].segments[seg].decomp_size; @@ -283,25 +276,19 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo /* Map in arguments. */ if (args != NULL && args_size) { - u64 arg_map_addr = 0; - if (R_FAILED((rc = MapUtils::LocateSpaceForMap(&arg_map_addr, extents->args_size)))) { + AutoCloseMap args_map; + if (R_FAILED((rc = args_map.Open(process_h, extents->args_address, extents->args_size)))) { return rc; } - NsoArgument *arg_map_base = (NsoArgument *)arg_map_addr; - - if (R_FAILED((rc = svcMapProcessMemory(arg_map_base, process_h, extents->args_address, extents->args_size)))) { - return rc; - } + NsoArgument *arg_map_base = (NsoArgument *)args_map.GetMappedAddress(); arg_map_base->allocated_space = extents->args_size; arg_map_base->args_size = args_size; std::fill(arg_map_base->_0x8, arg_map_base->_0x8 + sizeof(arg_map_base->_0x8), 0); std::copy(args, args + args_size, arg_map_base->arguments); - if (R_FAILED((rc = svcUnmapProcessMemory(arg_map_base, process_h, extents->args_address, extents->args_size)))) { - return rc; - } + args_map.Close(); if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->args_address, extents->args_size, 3)))) { return rc; diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 7ff8a676c..0299dbc64 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -104,6 +104,26 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig } +Result Registration::AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + /* TODO: panic() */ + return 0x7009; + } + + for (unsigned int i = 0; i < NSO_INFO_MAX; i++) { + if (!target_process->nrr_infos[i].in_use) { + target_process->nrr_infos[i].info.base_address = base_address; + target_process->nrr_infos[i].info.size = size; + target_process->nrr_infos[i].info.code_memory_address = code_memory_address; + target_process->nrr_infos[i].info.loader_address = loader_address; + return 0; + } + } + return 0x7009; +} + + Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { Registration::Process *target_process = GetProcessByProcessId(process_id); if (target_process == NULL) { diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 1c1483eec..53deb2aa5 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -23,7 +23,7 @@ class Registration { u64 base_address; u64 size; u64 code_memory_address; - u64 address_for_loader; + u64 loader_address; }; struct NrrInfoHolder { @@ -45,7 +45,7 @@ class Registration { Registration::TidSid tid_sid; Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX]; Registration::NrrInfoHolder nrr_infos[NRR_INFO_MAX]; - u64 _0x730; + void *owner_ro_service; }; struct List { @@ -61,5 +61,6 @@ class Registration { static bool UnregisterIndex(u64 index); static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); + static Result AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index 2375a0b0b..ff4ad97df 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -4,6 +4,7 @@ #include "ldr_ro_service.hpp" #include "ldr_registration.hpp" +#include "ldr_map.hpp" Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result rc = 0xF601; @@ -42,8 +43,34 @@ std::tuple RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, } std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { - /* TODO */ - return std::make_tuple(0xF601); + Result rc; + Registration::Process *target_proc; + if (!this->has_initialized || this->process_id != pid_desc.pid) { + rc = 0xAE09; + goto LOAD_NRR_END; + } + if (nrr_address & 0xFFF) { + rc = 0xA209; + goto LOAD_NRR_END; + } + if (nrr_address + nrr_size <= nrr_address || !nrr_size || (nrr_size & 0xFFF)) { + rc = 0xA409; + goto LOAD_NRR_END; + } + + target_proc = Registration::GetProcessByProcessId(pid_desc.pid); + if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) { + rc = 0xAC09; + goto LOAD_NRR_END; + } + target_proc->owner_ro_service = this; + + + /* TODO: Implement remainder of fucntion */ + rc = 0xDED09; + +LOAD_NRR_END: + return std::make_tuple(rc); } std::tuple RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, u64 nrr_address) { @@ -59,6 +86,7 @@ std::tuple RelocatableObjectsService::initialize(PidDescriptor pid_desc, svcCloseHandle(this->process_handle); } this->process_handle = process_h.handle; + this->process_id = handle_pid; this->has_initialized = true; rc = 0; }