From 8bae7b4a78f8fe5061596f354e38ecd0238cdaed Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 16 Sep 2019 01:22:08 -0700 Subject: [PATCH] dmnt: refactor to use sts:: namespace. --- Makefile | 2 +- include/stratosphere/dmnt.hpp | 20 ++++ .../stratosphere/dmnt/dmnt_cheat_types.hpp | 62 +++++++++++++ include/stratosphere/hossynch.hpp | 19 +++- include/stratosphere/pm.hpp | 3 +- include/stratosphere/pm/pm_dmnt_api.hpp | 32 +++++++ source/pm/pm_ams.c | 91 +++++++++++++++++++ source/pm/pm_ams.h | 3 + source/pm/pm_dmnt_api.cpp | 54 +++++++++++ 9 files changed, 281 insertions(+), 5 deletions(-) create mode 100644 include/stratosphere/dmnt.hpp create mode 100644 include/stratosphere/dmnt/dmnt_cheat_types.hpp create mode 100644 include/stratosphere/pm/pm_dmnt_api.hpp create mode 100644 source/pm/pm_dmnt_api.cpp diff --git a/Makefile b/Makefile index ea746be8..add6a081 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \ CFLAGS += $(INCLUDE) -D__SWITCH__ -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -flto -std=gnu++17 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) diff --git a/include/stratosphere/dmnt.hpp b/include/stratosphere/dmnt.hpp new file mode 100644 index 00000000..62539959 --- /dev/null +++ b/include/stratosphere/dmnt.hpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +#include "dmnt/dmnt_cheat_types.hpp" diff --git a/include/stratosphere/dmnt/dmnt_cheat_types.hpp b/include/stratosphere/dmnt/dmnt_cheat_types.hpp new file mode 100644 index 00000000..1edb9192 --- /dev/null +++ b/include/stratosphere/dmnt/dmnt_cheat_types.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "../ncm/ncm_types.hpp" + +namespace sts::dmnt::cheat { + + struct CheatProcessMetadata { + struct MemoryRegionExtents { + u64 base; + u64 size; + }; + + u64 process_id; + ncm::TitleId title_id; + MemoryRegionExtents main_nso_extents; + MemoryRegionExtents heap_extents; + MemoryRegionExtents alias_extents; + MemoryRegionExtents aslr_extents; + u8 main_nso_build_id[0x20]; + }; + + static_assert(std::is_pod::value && sizeof(CheatProcessMetadata) == 0x70, "CheatProcessMetadata definition!"); + + struct CheatDefinition { + char readable_name[0x40]; + uint32_t num_opcodes; + uint32_t opcodes[0x100]; + }; + + struct CheatEntry { + bool enabled; + uint32_t cheat_id; + CheatDefinition definition; + }; + + struct FrozenAddressValue { + u64 value; + u8 width; + }; + + struct FrozenAddressEntry { + u64 address; + FrozenAddressValue value; + }; + +} diff --git a/include/stratosphere/hossynch.hpp b/include/stratosphere/hossynch.hpp index 624dba80..2b654a74 100644 --- a/include/stratosphere/hossynch.hpp +++ b/include/stratosphere/hossynch.hpp @@ -224,24 +224,33 @@ class HosSignal { mutexUnlock(&m); } - void Wait() { + void Wait(bool reset = false) { mutexLock(&m); while (!signaled) { condvarWait(&cv, &m); } + if (reset) { + this->signaled = false; + } + mutexUnlock(&m); } - bool TryWait() { + bool TryWait(bool reset = false) { mutexLock(&m); + bool success = signaled; + if (reset) { + this->signaled = false; + } + mutexUnlock(&m); return success; } - Result TimedWait(u64 ns) { + Result TimedWait(u64 ns, bool reset = false) { mutexLock(&m); TimeoutHelper timeout_helper(ns); @@ -251,6 +260,10 @@ class HosSignal { } } + if (reset) { + this->signaled = false; + } + mutexUnlock(&m); return true; } diff --git a/include/stratosphere/pm.hpp b/include/stratosphere/pm.hpp index 92d8eef6..2a8d7976 100644 --- a/include/stratosphere/pm.hpp +++ b/include/stratosphere/pm.hpp @@ -20,4 +20,5 @@ #include "pm/pm_types.hpp" #include "pm/pm_boot_mode_api.hpp" #include "pm/pm_info_api.hpp" -#include "pm/pm_shell_api.hpp" \ No newline at end of file +#include "pm/pm_shell_api.hpp" +#include "pm/pm_dmnt_api.hpp" \ No newline at end of file diff --git a/include/stratosphere/pm/pm_dmnt_api.hpp b/include/stratosphere/pm/pm_dmnt_api.hpp new file mode 100644 index 00000000..607b4c43 --- /dev/null +++ b/include/stratosphere/pm/pm_dmnt_api.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "../ldr.hpp" +#include "pm_types.hpp" + +namespace sts::pm::dmnt { + + /* Debug Monitor API. */ + Result StartProcess(u64 process_id); + Result GetProcessId(u64 *out_process_id, const ncm::TitleId title_id); + Result GetApplicationProcessId(u64 *out_process_id); + Result HookToCreateApplicationProcess(Handle *out_handle); + Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::TitleLocation *out_loc, u64 process_id); + Result AtmosphereGetCurrentLimitInfo(u64 *out_current_value, u64 *out_limit_value, ResourceLimitGroup group, LimitableResource resource); + +} diff --git a/source/pm/pm_ams.c b/source/pm/pm_ams.c index 46882eb0..2e1c1988 100644 --- a/source/pm/pm_ams.c +++ b/source/pm/pm_ams.c @@ -94,3 +94,94 @@ Result pminfoAtmosphereHasLaunchedTitle(bool *out, u64 tid) { return rc; } + +Result pmdmntAtmosphereGetProcessInfo(Handle* out, u64 *tid_out, u8 *sid_out, u64 pid) { + IpcCommand c; + ipcInitialize(&c); + Service *s = pmdmntGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65000; + raw->pid = pid; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 title_id; + FsStorageId storage_id; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (out) { + *out = r.Handles[0]; + } else { + svcCloseHandle(r.Handles[0]); + } + if (tid_out) *tid_out = resp->title_id; + if (sid_out) *sid_out = resp->storage_id; + } + } + + return rc; +} + +Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource) { + IpcCommand c; + ipcInitialize(&c); + Service *s = pmdmntGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u32 group; + u32 resource; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65001; + raw->group = group; + raw->resource = resource; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 cur_value; + u64 lim_value; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (out_cur) *out_cur = resp->cur_value; + if (out_lim) *out_lim = resp->lim_value; + } + } + + return rc; +} diff --git a/source/pm/pm_ams.h b/source/pm/pm_ams.h index 78bc9ce9..11887971 100644 --- a/source/pm/pm_ams.h +++ b/source/pm/pm_ams.h @@ -14,6 +14,9 @@ extern "C" { Result pminfoAtmosphereGetProcessId(u64 *out_pid, u64 tid); Result pminfoAtmosphereHasLaunchedTitle(bool *out, u64 tid); +Result pmdmntAtmosphereGetProcessInfo(Handle *out, u64 *tid_out, u8 *sid_out, u64 pid); +Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/source/pm/pm_dmnt_api.cpp b/source/pm/pm_dmnt_api.cpp new file mode 100644 index 00000000..2ea35478 --- /dev/null +++ b/source/pm/pm_dmnt_api.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "pm_ams.h" + +namespace sts::pm::dmnt { + + /* Debug Monitor API. */ + Result StartProcess(u64 process_id) { + return pmdmntStartProcess(process_id); + } + + Result GetProcessId(u64 *out_process_id, const ncm::TitleId title_id) { + return pmdmntGetTitlePid(out_process_id, static_cast(title_id)); + } + + Result GetApplicationProcessId(u64 *out_process_id) { + return pmdmntGetApplicationPid(out_process_id); + } + + Result HookToCreateApplicationProcess(Handle *out_handle) { + return pmdmntEnableDebugForApplication(out_handle); + } + + Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::TitleLocation *out_loc, u64 process_id) { + *out_handle = INVALID_HANDLE; + *out_loc = {}; + return pmdmntAtmosphereGetProcessInfo(out_handle, reinterpret_cast(&out_loc->title_id), &out_loc->storage_id, process_id); + } + + Result AtmosphereGetCurrentLimitInfo(u64 *out_current_value, u64 *out_limit_value, ResourceLimitGroup group, LimitableResource resource) { + *out_current_value = 0; + *out_limit_value = 0; + return pmdmntAtmosphereGetCurrentLimitInfo(out_current_value, out_limit_value, group, resource); + } + +}