|
|
@ -1983,6 +1983,83 @@ static ResultCode SetResourceLimitLimitValue(Handle resource_limit, u32 resource |
|
|
return RESULT_SUCCESS; |
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ResultCode GetThreadList(u32* out_num_threads, VAddr out_thread_ids, u32 out_thread_ids_size, |
|
|
|
|
|
Handle debug_handle) { |
|
|
|
|
|
// TODO: Handle this case when debug events are supported.
|
|
|
|
|
|
UNIMPLEMENTED_IF(debug_handle != InvalidHandle); |
|
|
|
|
|
|
|
|
|
|
|
LOG_DEBUG(Kernel_SVC, "called. out_thread_ids=0x{:016X}, out_thread_ids_size={}", |
|
|
|
|
|
out_thread_ids, out_thread_ids_size); |
|
|
|
|
|
|
|
|
|
|
|
// If the size is negative or larger than INT32_MAX / sizeof(u64)
|
|
|
|
|
|
if ((out_thread_ids_size & 0xF0000000) != 0) { |
|
|
|
|
|
LOG_ERROR(Kernel_SVC, "Supplied size outside [0, 0x0FFFFFFF] range. size={}", |
|
|
|
|
|
out_thread_ids_size); |
|
|
|
|
|
return ERR_OUT_OF_RANGE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess(); |
|
|
|
|
|
const auto& vm_manager = current_process->VMManager(); |
|
|
|
|
|
const auto total_copy_size = out_thread_ids_size * sizeof(u64); |
|
|
|
|
|
|
|
|
|
|
|
if (out_thread_ids_size > 0 && |
|
|
|
|
|
!vm_manager.IsWithinAddressSpace(out_thread_ids, total_copy_size)) { |
|
|
|
|
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", |
|
|
|
|
|
out_thread_ids, out_thread_ids + total_copy_size); |
|
|
|
|
|
return ERR_INVALID_ADDRESS_STATE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const auto& thread_list = current_process->GetThreadList(); |
|
|
|
|
|
const auto num_threads = thread_list.size(); |
|
|
|
|
|
const auto copy_amount = std::min(std::size_t{out_thread_ids_size}, num_threads); |
|
|
|
|
|
|
|
|
|
|
|
auto list_iter = thread_list.cbegin(); |
|
|
|
|
|
for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) { |
|
|
|
|
|
Memory::Write64(out_thread_ids, (*list_iter)->GetThreadID()); |
|
|
|
|
|
out_thread_ids += sizeof(u64); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*out_num_threads = static_cast<u32>(num_threads); |
|
|
|
|
|
return RESULT_SUCCESS; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
namespace { |
|
|
namespace { |
|
|
struct FunctionDef { |
|
|
struct FunctionDef { |
|
|
using Func = void(); |
|
|
using Func = void(); |
|
|
@ -2095,8 +2172,8 @@ static const FunctionDef SVC_Table[] = { |
|
|
{0x62, nullptr, "TerminateDebugProcess"}, |
|
|
{0x62, nullptr, "TerminateDebugProcess"}, |
|
|
{0x63, nullptr, "GetDebugEvent"}, |
|
|
{0x63, nullptr, "GetDebugEvent"}, |
|
|
{0x64, nullptr, "ContinueDebugEvent"}, |
|
|
{0x64, nullptr, "ContinueDebugEvent"}, |
|
|
{0x65, nullptr, "GetProcessList"}, |
|
|
|
|
|
{0x66, nullptr, "GetThreadList"}, |
|
|
|
|
|
|
|
|
{0x65, SvcWrap<GetProcessList>, "GetProcessList"}, |
|
|
|
|
|
{0x66, SvcWrap<GetThreadList>, "GetThreadList"}, |
|
|
{0x67, nullptr, "GetDebugThreadContext"}, |
|
|
{0x67, nullptr, "GetDebugThreadContext"}, |
|
|
{0x68, nullptr, "SetDebugThreadContext"}, |
|
|
{0x68, nullptr, "SetDebugThreadContext"}, |
|
|
{0x69, nullptr, "QueryDebugProcessMemory"}, |
|
|
{0x69, nullptr, "QueryDebugProcessMemory"}, |
|
|
|