ProcessManager: Fully implement pm:dmnt. Remove debug logging.

This commit is contained in:
Michael Scire 2018-05-07 04:45:44 -06:00
parent 6dc8ab6f17
commit ae78ee22da
10 changed files with 230 additions and 42 deletions

View file

@ -1,14 +1,11 @@
#include <switch.h>
#include "pm_boot_mode.hpp"
#include "pm_debug.hpp"
static bool g_is_maintenance_boot = false;
Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
LogForService("BOOTMODE\x00", 8);
LogForService(&cmd_id, 8);
LogForService(armGetTls(), 0x100);
switch ((BootModeCmd)cmd_id) {
case BootMode_Cmd_GetBootMode:
rc = WrapIpcCommandImpl<&BootModeService::get_boot_mode>(this, r, out_c, pointer_buffer, pointer_buffer_size);
@ -19,10 +16,7 @@ Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd
default:
break;
}
LogForService(armGetTls(), 0x100);
if (R_FAILED(rc)) {
Reboot();
}
return rc;
}

View file

@ -0,0 +1,119 @@
#include <switch.h>
#include "pm_registration.hpp"
#include "pm_debug_monitor.hpp"
Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
if (kernelAbove500()) {
switch ((DmntCmd_5X)cmd_id) {
case Dmnt_Cmd_5X_GetDebugProcessIds:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_debug_process_ids>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_LaunchDebugProcess:
rc = WrapIpcCommandImpl<&DebugMonitorService::launch_debug_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_GetTitleProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_title_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_EnableDebugForTitleId:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_GetApplicationProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_EnableDebugForApplication:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
} else {
switch ((DmntCmd)cmd_id) {
case Dmnt_Cmd_GetUnknownStub:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_unknown_stub>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_GetDebugProcessIds:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_debug_process_ids>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_LaunchDebugProcess:
rc = WrapIpcCommandImpl<&DebugMonitorService::launch_debug_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_GetTitleProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_title_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_EnableDebugForTitleId:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_GetApplicationProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_EnableDebugForApplication:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
}
return rc;
}
Result DebugMonitorService::handle_deferred() {
/* This service is never deferrable. */
return 0;
}
std::tuple<Result, u32> DebugMonitorService::get_unknown_stub(u64 unknown, OutBuffer<u8> out_unknown) {
/* This command seem stubbed on retail. */
if (out_unknown.num_elements >> 31) {
return {0xC0F, 0};
}
return {0x0, 0};
}
std::tuple<Result, u32> DebugMonitorService::get_debug_process_ids(OutBuffer<u64> out_pids) {
u32 num_out = 0;
Result rc;
if (out_pids.num_elements >> 31) {
return {0xC0F, 0};
}
rc = Registration::GetDebugProcessIds(out_pids.buffer, out_pids.num_elements, &num_out);
return {rc, num_out};
}
std::tuple<Result> DebugMonitorService::launch_debug_process(u64 pid) {
return {Registration::LaunchDebugProcess(pid)};
}
std::tuple<Result, u64> DebugMonitorService::get_title_process_id(u64 tid) {
Registration::AutoProcessListLock auto_lock;
Registration::Process *proc = Registration::GetProcessByTitleId(tid);
if (proc != NULL) {
return {0, proc->pid};
} else {
return {0x20F, 0};
}
}
std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_tid(u64 tid) {
Handle h = 0;
Result rc = Registration::EnableDebugForTitleId(tid, &h);
return {rc, h};
}
std::tuple<Result, u64> DebugMonitorService::get_application_process_id() {
Registration::AutoProcessListLock auto_lock;
Registration::Process *app_proc;
if (Registration::HasApplicationProcess(&app_proc)) {
return {0, app_proc->pid};
}
return {0x20F, 0};
}
std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_application() {
Handle h = 0;
Result rc = Registration::EnableDebugForApplication(&h);
return {rc, h};
}

View file

@ -0,0 +1,40 @@
#pragma once
#include <switch.h>
#include <stratosphere/iserviceobject.hpp>
#include "pm_registration.hpp"
enum DmntCmd {
Dmnt_Cmd_GetUnknownStub = 0,
Dmnt_Cmd_GetDebugProcessIds = 1,
Dmnt_Cmd_LaunchDebugProcess = 2,
Dmnt_Cmd_GetTitleProcessId = 3,
Dmnt_Cmd_EnableDebugForTitleId = 4,
Dmnt_Cmd_GetApplicationProcessId = 5,
Dmnt_Cmd_EnableDebugForApplication = 6,
};
enum DmntCmd_5X {
Dmnt_Cmd_5X_GetDebugProcessIds = 0,
Dmnt_Cmd_5X_LaunchDebugProcess = 1,
Dmnt_Cmd_5X_GetTitleProcessId = 2,
Dmnt_Cmd_5X_EnableDebugForTitleId = 3,
Dmnt_Cmd_5X_GetApplicationProcessId = 4,
Dmnt_Cmd_5X_EnableDebugForApplication = 5,
};
class DebugMonitorService : IServiceObject {
public:
virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
virtual Result handle_deferred();
private:
/* Actual commands. */
std::tuple<Result, u32> get_unknown_stub(u64 unknown, OutBuffer<u8> out_unknown);
std::tuple<Result, u32> get_debug_process_ids(OutBuffer<u64> out_processes);
std::tuple<Result> launch_debug_process(u64 pid);
std::tuple<Result, u64> get_title_process_id(u64 tid);
std::tuple<Result, CopiedHandle> enable_debug_for_tid(u64 tid);
std::tuple<Result, u64> get_application_process_id();
std::tuple<Result, CopiedHandle> enable_debug_for_application();
};

View file

@ -1,13 +1,10 @@
#include <switch.h>
#include "pm_registration.hpp"
#include "pm_info.hpp"
#include "pm_debug.hpp"
Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
LogForService("INFOSRV\x00", 8);
LogForService(&cmd_id, 8);
LogForService(armGetTls(), 0x100);
switch ((InformationCmd)cmd_id) {
case Information_Cmd_GetTitleId:
rc = WrapIpcCommandImpl<&InformationService::get_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
@ -15,10 +12,7 @@ Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64
default:
break;
}
LogForService(armGetTls(), 0x100);
if (R_FAILED(rc)) {
Reboot();
}
return rc;
}

View file

@ -11,7 +11,7 @@
#include "pm_shell.hpp"
#include "pm_process_track.hpp"
#include "pm_registration.hpp"
#include "pm_debug.hpp"
#include "pm_debug_monitor.hpp"
extern "C" {
extern u32 __start__;
@ -111,6 +111,7 @@ int main(int argc, char **argv)
/* TODO: Create services. */
server_manager->add_waitable(new ServiceServer<ShellService>("pm:shell", 3));
server_manager->add_waitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2));
server_manager->add_waitable(new ServiceServer<BootModeService>("pm:bm", 5));
server_manager->add_waitable(new ServiceServer<InformationService>("pm:info", 1));

View file

@ -2,7 +2,6 @@
#include <stratosphere.hpp>
#include "pm_process_track.hpp"
#include "pm_registration.hpp"
#include "pm_debug.hpp"
void ProcessTracking::MainLoop(void *arg) {
/* Make a new waitable manager. */

View file

@ -2,9 +2,6 @@
#include <switch.h>
#include <stratosphere.hpp>
#include "pm_registration.hpp"
#include "pm_debug.hpp"
class ProcessWaiter : public IWaitable {
public:
Registration::Process process;

View file

@ -150,8 +150,6 @@ void Registration::HandleProcessLaunch() {
if (R_SUCCEEDED(rc)) {
SetProcessState(new_process.pid, ProcessState_DebugDetached);
Log("MADENEWPROCESS", 16);
Log(GetProcess(new_process.pid), sizeof(Process));
}
}
@ -185,6 +183,32 @@ HANDLE_PROCESS_LAUNCH_END:
}
Result Registration::LaunchDebugProcess(u64 pid) {
AutoProcessListLock auto_lock;
LoaderProgramInfo program_info = {0};
Result rc;
Process *proc = GetProcess(pid);
if (proc == NULL) {
return 0x20F;
}
if (proc->state >= ProcessState_DebugDetached) {
return 0x40F;
}
/* Check that this is a real program. */
if (R_FAILED((rc = ldrPmGetProgramInfo(proc->tid_sid.title_id, proc->tid_sid.storage_id, &program_info)))) {
return rc;
}
if (R_SUCCEEDED((rc = svcStartProcess(proc->handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size)))) {
proc->state = ProcessState_DebugDetached;
}
return rc;
}
Result Registration::LaunchProcess(u64 title_id, FsStorageId storage_id, u64 launch_flags, u64 *out_pid) {
Result rc;
/* Only allow one mutex to exist. */
@ -211,9 +235,6 @@ Result Registration::LaunchProcessByTidSid(TidSid tid_sid, u64 launch_flags, u64
void Registration::HandleSignaledProcess(Process *process) {
u64 tmp;
Log("PROCESSIGNALED\x00", 16);
Log(process, sizeof(*process));
/* Reset the signal. */
svcResetSignal(process->handle);
@ -221,7 +242,6 @@ void Registration::HandleSignaledProcess(Process *process) {
old_state = process->state;
svcGetProcessInfo(&tmp, process->handle, ProcessInfoType_ProcessState);
process->state = (ProcessState)tmp;
Log(process, sizeof(*process));
if (old_state == ProcessState_Crashed && process->state != ProcessState_Crashed) {
process->flags &= ~0x4;
@ -381,6 +401,23 @@ Registration::Process *Registration::GetProcessByTitleId(u64 tid) {
return NULL;
}
Result Registration::GetDebugProcessIds(u64 *out_pids, u32 max_out, u32 *num_out) {
AutoProcessListLock auto_lock;
u32 num = 0;
for (auto &pw : g_process_list.process_waiters) {
Process *p = pw->get_process();
if (p->flags & 4 && num < max_out) {
out_pids[num++] = p->pid;
}
}
*num_out = num;
return 0;
}
Handle Registration::GetProcessEventHandle() {
return g_process_event->get_handle();
}
@ -433,10 +470,19 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) {
*out_type = 0;
}
Handle Registration::GetDebugTitleEventHandle() {
return g_debug_title_event->get_handle();
Result Registration::EnableDebugForTitleId(u64 tid, Handle *out) {
u64 old = g_debug_on_launch_tid.exchange(tid);
if (old) {
g_debug_on_launch_tid = old;
return 0x80F;
}
*out = g_debug_title_event->get_handle();
return 0x0;
}
Handle Registration::GetDebugApplicationEventHandle() {
return g_debug_application_event->get_handle();
Result Registration::EnableDebugForApplication(Handle *out) {
g_debug_next_application = true;
*out = g_debug_application_event->get_handle();
return 0;
}

View file

@ -54,12 +54,16 @@ class Registration {
static Process *GetProcess(u64 pid);
static Process *GetProcessByTitleId(u64 tid);
static Result GetDebugProcessIds(u64 *out_pids, u32 max_out, u32 *num_out);
static Handle GetProcessEventHandle();
static void GetProcessEventType(u64 *out_pid, u64 *out_type);
static Result EnableDebugForTitleId(u64 tid, Handle *out);
static Result EnableDebugForApplication(Handle *out);
static Handle GetDebugTitleEventHandle();
static Handle GetDebugApplicationEventHandle();
static void HandleProcessLaunch();
static Result LaunchDebugProcess(u64 pid);
static void SignalFinishLaunchProcess();
static Result LaunchProcess(u64 title_id, FsStorageId storage_id, u64 launch_flags, u64 *out_pid);
static Result LaunchProcessByTidSid(TidSid tid_sid, u64 launch_flags, u64 *out_pid);

View file

@ -2,15 +2,12 @@
#include "pm_registration.hpp"
#include "pm_resource_limits.hpp"
#include "pm_shell.hpp"
#include "pm_debug.hpp"
static bool g_has_boot_finished = false;
Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
LogForService("SHELLSRV", 8);
LogForService(&cmd_id, 8);
LogForService(armGetTls(), 0x100);
if (kernelAbove500()) {
switch ((ShellCmd_5X)cmd_id) {
case Shell_Cmd_5X_LaunchProcess:
@ -37,6 +34,8 @@ Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id
case Shell_Cmd_5X_BoostSystemMemoryResourceLimit:
rc = WrapIpcCommandImpl<&ShellService::boost_system_memory_resource_limit>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
} else {
switch ((ShellCmd)cmd_id) {
@ -74,12 +73,7 @@ Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id
break;
}
}
//Log(armGetTls(), 0x100);
LogForService(armGetTls(), 0x100);
if (R_FAILED(rc)) {
Reboot();
}
return rc;
}