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.
This commit is contained in:
		| @@ -191,6 +191,10 @@ const Process* KernelCore::CurrentProcess() const { | ||||
|     return impl->current_process; | ||||
| } | ||||
|  | ||||
| const std::vector<SharedPtr<Process>>& KernelCore::GetProcessList() const { | ||||
|     return impl->process_list; | ||||
| } | ||||
|  | ||||
| void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) { | ||||
|     impl->named_ports.emplace(std::move(name), std::move(port)); | ||||
| } | ||||
|   | ||||
| @@ -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<SharedPtr<Process>>& GetProcessList() const; | ||||
|  | ||||
|     /// Adds a port to the named port table | ||||
|     void AddNamedPort(std::string name, SharedPtr<ClientPort> port); | ||||
|  | ||||
|   | ||||
| @@ -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<u32>(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>, "GetProcessList"}, | ||||
|     {0x66, nullptr, "GetThreadList"}, | ||||
|     {0x67, nullptr, "GetDebugThreadContext"}, | ||||
|     {0x68, nullptr, "SetDebugThreadContext"}, | ||||
|   | ||||
| @@ -78,6 +78,14 @@ void SvcWrap() { | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| template <ResultCode func(u32*, u64, u32)> | ||||
| void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     const u32 retval = func(¶m_1, Param(1), static_cast<u32>(Param(2))).raw; | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| template <ResultCode func(u64*, u32)> | ||||
| void SvcWrap() { | ||||
|     u64 param_1 = 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Lioncash
					Lioncash