kern: implement SvcDebugActiveProcess, svcGetDebugEvent, SvcWaitProcessWideKeyAtomic

This commit is contained in:
Michael Scire 2020-07-18 20:03:27 -07:00 committed by SciresM
parent 1c5b58ce66
commit 36eb78a3ce
17 changed files with 728 additions and 24 deletions

View file

@ -21,7 +21,37 @@ namespace ams::kern::svc {
namespace {
constexpr bool IsKernelAddress(uintptr_t address) {
return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
}
Result WaitProcessWideKeyAtomic(uintptr_t address, uintptr_t cv_key, uint32_t tag, int64_t timeout_ns) {
/* Validate input. */
R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress());
/* Convert timeout from nanoseconds to ticks. */
s64 timeout;
if (timeout_ns > 0) {
const ams::svc::Tick offset_tick(TimeSpan::FromNanoSeconds(timeout_ns));
if (AMS_LIKELY(offset_tick > 0)) {
timeout = KHardwareTimer::GetTick() + offset_tick + 2;
if (AMS_UNLIKELY(timeout <= 0)) {
timeout = std::numeric_limits<s64>::max();
}
} else {
timeout = std::numeric_limits<s64>::max();
}
} else {
timeout = timeout_ns;
}
/* Wait on the condition variable. */
return GetCurrentProcess().WaitConditionVariable(address, util::AlignDown(cv_key, sizeof(u32)), tag, timeout);
}
void SignalProcessWideKey(uintptr_t cv_key, int32_t count) {
/* Signal the condition variable. */
return GetCurrentProcess().SignalConditionVariable(util::AlignDown(cv_key, sizeof(u32)), count);
}
@ -30,7 +60,7 @@ namespace ams::kern::svc {
/* ============================= 64 ABI ============================= */
Result WaitProcessWideKeyAtomic64(ams::svc::Address address, ams::svc::Address cv_key, uint32_t tag, int64_t timeout_ns) {
MESOSPHERE_PANIC("Stubbed SvcWaitProcessWideKeyAtomic64 was called.");
return WaitProcessWideKeyAtomic(address, cv_key, tag, timeout_ns);
}
void SignalProcessWideKey64(ams::svc::Address cv_key, int32_t count) {
@ -40,7 +70,7 @@ namespace ams::kern::svc {
/* ============================= 64From32 ABI ============================= */
Result WaitProcessWideKeyAtomic64From32(ams::svc::Address address, ams::svc::Address cv_key, uint32_t tag, int64_t timeout_ns) {
MESOSPHERE_PANIC("Stubbed SvcWaitProcessWideKeyAtomic64From32 was called.");
return WaitProcessWideKeyAtomic(address, cv_key, tag, timeout_ns);
}
void SignalProcessWideKey64From32(ams::svc::Address cv_key, int32_t count) {

View file

@ -21,14 +21,70 @@ namespace ams::kern::svc {
namespace {
Result DebugActiveProcess(ams::svc::Handle *out_handle, uint64_t process_id) {
/* Get the process from its id. */
KProcess *process = KProcess::GetProcessFromId(process_id);
R_UNLESS(process != nullptr, svc::ResultInvalidProcessId());
/* Close the reference we opened to the process on scope exit. */
ON_SCOPE_EXIT { process->Close(); };
/* Check that the debugging is allowed. */
if (!process->IsPermittedDebug()) {
R_UNLESS(GetCurrentProcess().CanForceDebug(), svc::ResultInvalidState());
}
/* Disallow debugging one's own processs, to prevent softlocks. */
R_UNLESS(process != GetCurrentProcessPointer(), svc::ResultInvalidState());
/* Get the current handle table. */
auto &handle_table = GetCurrentProcess().GetHandleTable();
/* Create a new debug object. */
KDebug *debug = KDebug::Create();
R_UNLESS(debug != nullptr, svc::ResultOutOfResource());
ON_SCOPE_EXIT { debug->Close(); };
/* Initialize the debug object. */
debug->Initialize();
/* Register the debug object. */
KDebug::Register(debug);
/* Try to attach to the target process. */
R_TRY(debug->Attach(process));
/* Add the new debug object to the handle table. */
R_TRY(handle_table.Add(out_handle, debug));
return ResultSuccess();
}
template<typename EventInfoType>
Result GetDebugEvent(KUserPointer<EventInfoType *> out_info, ams::svc::Handle debug_handle) {
/* Get the debug object. */
KScopedAutoObject debug = GetCurrentProcess().GetHandleTable().GetObject<KDebug>(debug_handle);
R_UNLESS(debug.IsNotNull(), svc::ResultInvalidHandle());
/* Create and clear a new event info. */
EventInfoType info;
std::memset(std::addressof(info), 0, sizeof(info));
/* Get the next info from the debug object. */
R_TRY(debug->GetDebugEventInfo(std::addressof(info)));
/* Copy the info out to the user. */
R_TRY(out_info.CopyFrom(std::addressof(info)));
return ResultSuccess();
}
}
/* ============================= 64 ABI ============================= */
Result DebugActiveProcess64(ams::svc::Handle *out_handle, uint64_t process_id) {
MESOSPHERE_PANIC("Stubbed SvcDebugActiveProcess64 was called.");
return DebugActiveProcess(out_handle, process_id);
}
Result BreakDebugProcess64(ams::svc::Handle debug_handle) {
@ -40,7 +96,7 @@ namespace ams::kern::svc {
}
Result GetDebugEvent64(KUserPointer<ams::svc::lp64::DebugEventInfo *> out_info, ams::svc::Handle debug_handle) {
MESOSPHERE_PANIC("Stubbed SvcGetDebugEvent64 was called.");
return GetDebugEvent(out_info, debug_handle);
}
Result ContinueDebugEvent64(ams::svc::Handle debug_handle, uint32_t flags, KUserPointer<const uint64_t *> thread_ids, int32_t num_thread_ids) {
@ -82,7 +138,7 @@ namespace ams::kern::svc {
/* ============================= 64From32 ABI ============================= */
Result DebugActiveProcess64From32(ams::svc::Handle *out_handle, uint64_t process_id) {
MESOSPHERE_PANIC("Stubbed SvcDebugActiveProcess64From32 was called.");
return DebugActiveProcess(out_handle, process_id);
}
Result BreakDebugProcess64From32(ams::svc::Handle debug_handle) {
@ -94,7 +150,7 @@ namespace ams::kern::svc {
}
Result GetDebugEvent64From32(KUserPointer<ams::svc::ilp32::DebugEventInfo *> out_info, ams::svc::Handle debug_handle) {
MESOSPHERE_PANIC("Stubbed SvcGetDebugEvent64From32 was called.");
return GetDebugEvent(out_info, debug_handle);
}
Result ContinueDebugEvent64From32(ams::svc::Handle debug_handle, uint32_t flags, KUserPointer<const uint64_t *> thread_ids, int32_t num_thread_ids) {

View file

@ -35,17 +35,18 @@ namespace ams::kern::svc {
R_UNLESS((das_address < das_address + das_size), svc::ResultInvalidMemoryRegion());
/* Create the device address space. */
KScopedAutoObject das = KDeviceAddressSpace::Create();
R_UNLESS(das.IsNotNull(), svc::ResultOutOfResource());
KDeviceAddressSpace *das = KDeviceAddressSpace::Create();
R_UNLESS(das != nullptr, svc::ResultOutOfResource());
ON_SCOPE_EXIT { das->Close(); };
/* Initialize the device address space. */
R_TRY(das->Initialize(das_address, das_size));
/* Register the device address space. */
R_TRY(KDeviceAddressSpace::Register(das.GetPointerUnsafe()));
R_TRY(KDeviceAddressSpace::Register(das));
/* Add to the handle table. */
R_TRY(GetCurrentProcess().GetHandleTable().Add(out, das.GetPointerUnsafe()));
R_TRY(GetCurrentProcess().GetHandleTable().Add(out, das));
return ResultSuccess();
}

View file

@ -43,17 +43,18 @@ namespace ams::kern::svc {
auto &handle_table = process.GetHandleTable();
/* Create the interrupt event. */
KScopedAutoObject event = KInterruptEvent::Create();
R_UNLESS(event.IsNotNull(), svc::ResultOutOfResource());
KInterruptEvent *event = KInterruptEvent::Create();
R_UNLESS(event != nullptr, svc::ResultOutOfResource());
ON_SCOPE_EXIT { event->Close(); };
/* Initialize the event. */
R_TRY(event->Initialize(interrupt_id, type));
/* Register the event. */
R_TRY(KInterruptEvent::Register(event.GetPointerUnsafe()));
R_TRY(KInterruptEvent::Register(event));
/* Add the event to the handle table. */
R_TRY(handle_table.Add(out, event.GetPointerUnsafe()));
R_TRY(handle_table.Add(out, event));
return ResultSuccess();
}

View file

@ -44,13 +44,14 @@ namespace ams::kern::svc {
R_UNLESS(thread_reservation.Succeeded(), svc::ResultLimitReached());
/* Create the thread. */
KScopedAutoObject thread = KThread::Create();
R_UNLESS(thread.IsNotNull(), svc::ResultOutOfResource());
KThread *thread = KThread::Create();
R_UNLESS(thread != nullptr, svc::ResultOutOfResource());
ON_SCOPE_EXIT { thread->Close(); };
/* Initialize the thread. */
{
KScopedLightLock lk(process.GetStateLock());
R_TRY(KThread::InitializeUserThread(thread.GetPointerUnsafe(), reinterpret_cast<KThreadFunction>(static_cast<uintptr_t>(f)), arg, stack_bottom, priority, core_id, std::addressof(process)));
R_TRY(KThread::InitializeUserThread(thread, reinterpret_cast<KThreadFunction>(static_cast<uintptr_t>(f)), arg, stack_bottom, priority, core_id, std::addressof(process)));
}
/* Commit the thread reservation. */
@ -60,10 +61,10 @@ namespace ams::kern::svc {
thread->GetContext().CloneFpuStatus();
/* Register the new thread. */
R_TRY(KThread::Register(thread.GetPointerUnsafe()));
R_TRY(KThread::Register(thread));
/* Add the thread to the handle table. */
R_TRY(process.GetHandleTable().Add(out, thread.GetPointerUnsafe()));
R_TRY(process.GetHandleTable().Add(out, thread));
return ResultSuccess();
}