From cb2bce8006189d866fb468b497d1ddcf2fd99ccf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 20 Mar 2019 15:03:52 -0400 Subject: kernel/svc: Implement svcGetProcessList This service function simply copies out a specified number of kernel process IDs, while simultaneously reporting the total number of processes. --- src/core/hle/kernel/kernel.cpp | 4 ++++ src/core/hle/kernel/kernel.h | 3 +++ src/core/hle/kernel/svc.cpp | 39 ++++++++++++++++++++++++++++++++++++++- src/core/hle/kernel/svc_wrap.h | 8 ++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 6baeb3494..ea1c13cdf 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -191,6 +191,10 @@ const Process* KernelCore::CurrentProcess() const { return impl->current_process; } +const std::vector>& KernelCore::GetProcessList() const { + return impl->process_list; +} + void KernelCore::AddNamedPort(std::string name, SharedPtr port) { impl->named_ports.emplace(std::move(name), std::move(port)); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 03ea5b659..6b8738599 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -72,6 +72,9 @@ public: /// Retrieves a const pointer to the current process. const Process* CurrentProcess() const; + /// Retrieves the list of processes. + const std::vector>& GetProcessList() const; + /// Adds a port to the named port table void AddNamedPort(std::string name, SharedPtr port); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 76a8b0191..3cd948bb5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1983,6 +1983,43 @@ static ResultCode SetResourceLimitLimitValue(Handle resource_limit, u32 resource return RESULT_SUCCESS; } +static ResultCode GetProcessList(u32* out_num_processes, VAddr out_process_ids, + u32 out_process_ids_size) { + LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}", + out_process_ids, out_process_ids_size); + + // If the supplied size is negative or greater than INT32_MAX / sizeof(u64), bail. + if ((out_process_ids_size & 0xF0000000) != 0) { + LOG_ERROR(Kernel_SVC, + "Supplied size outside [0, 0x0FFFFFFF] range. out_process_ids_size={}", + out_process_ids_size); + return ERR_OUT_OF_RANGE; + } + + const auto& kernel = Core::System::GetInstance().Kernel(); + const auto& vm_manager = kernel.CurrentProcess()->VMManager(); + const auto total_copy_size = out_process_ids_size * sizeof(u64); + + if (out_process_ids_size > 0 && + !vm_manager.IsWithinAddressSpace(out_process_ids, total_copy_size)) { + LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", + out_process_ids, out_process_ids + total_copy_size); + return ERR_INVALID_ADDRESS_STATE; + } + + const auto& process_list = kernel.GetProcessList(); + const auto num_processes = process_list.size(); + const auto copy_amount = std::min(std::size_t{out_process_ids_size}, num_processes); + + for (std::size_t i = 0; i < copy_amount; ++i) { + Memory::Write64(out_process_ids, process_list[i]->GetProcessID()); + out_process_ids += sizeof(u64); + } + + *out_num_processes = static_cast(num_processes); + return RESULT_SUCCESS; +} + namespace { struct FunctionDef { using Func = void(); @@ -2095,7 +2132,7 @@ static const FunctionDef SVC_Table[] = { {0x62, nullptr, "TerminateDebugProcess"}, {0x63, nullptr, "GetDebugEvent"}, {0x64, nullptr, "ContinueDebugEvent"}, - {0x65, nullptr, "GetProcessList"}, + {0x65, SvcWrap, "GetProcessList"}, {0x66, nullptr, "GetThreadList"}, {0x67, nullptr, "GetDebugThreadContext"}, {0x68, nullptr, "SetDebugThreadContext"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 2a2c2c5ea..b3733680f 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -78,6 +78,14 @@ void SvcWrap() { FuncReturn(retval); } +template +void SvcWrap() { + u32 param_1 = 0; + const u32 retval = func(¶m_1, Param(1), static_cast(Param(2))).raw; + Core::CurrentArmInterface().SetReg(1, param_1); + FuncReturn(retval); +} + template void SvcWrap() { u64 param_1 = 0; -- cgit v1.2.3