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

@ -30,6 +30,11 @@ namespace ams::kern::arch::arm64 {
class KDebug final : public KAutoObjectWithSlabHeapAndContainer<KDebug, KDebugBase> {
MESOSPHERE_AUTOOBJECT_TRAITS(KDebug, KSynchronizationObject);
public:
explicit KDebug() { /* ... */ }
virtual ~KDebug() { /* ... */ }
static void PostDestroy(uintptr_t arg) { /* ... */ }
/* TODO: This is a placeholder definition. */
};

View file

@ -283,6 +283,14 @@ namespace ams::kern {
}
}
constexpr bool IsPermittedDebug() const {
return this->debug_capabilities.Get<DebugFlags::AllowDebug>();
}
constexpr bool CanForceDebug() const {
return this->debug_capabilities.Get<DebugFlags::ForceDebug>();
}
/* TODO: Member functions. */
};

View file

@ -16,12 +16,42 @@
#pragma once
#include <mesosphere/kern_common.hpp>
#include <mesosphere/kern_k_synchronization_object.hpp>
#include <mesosphere/kern_k_process.hpp>
#include <mesosphere/kern_k_event_info.hpp>
#include <mesosphere/kern_k_light_lock.hpp>
namespace ams::kern {
class KDebugBase : public KSynchronizationObject {
protected:
using DebugEventList = util::IntrusiveListBaseTraits<KEventInfo>::ListType;
private:
DebugEventList event_info_list;
u32 continue_flags;
KProcess *process;
KLightLock lock;
KProcess::State old_process_state;
public:
explicit KDebugBase() { /* ... */ }
virtual ~KDebugBase() { /* ... */ }
public:
void Initialize();
Result Attach(KProcess *process);
Result GetDebugEventInfo(ams::svc::lp64::DebugEventInfo *out);
Result GetDebugEventInfo(ams::svc::ilp32::DebugEventInfo *out);
/* TODO: This is a placeholder definition. */
private:
KScopedAutoObject<KProcess> GetProcess();
void PushDebugEvent(ams::svc::DebugEvent event, uintptr_t param0 = 0, uintptr_t param1 = 0, uintptr_t param2 = 0, uintptr_t param3 = 0, uintptr_t param4 = 0);
void EnqueueDebugEventInfo(KEventInfo *info);
public:
virtual void OnFinalizeSynchronizationObject() override;
virtual bool IsSignaled() const override;
public:
static KEventInfo *CreateDebugEvent(ams::svc::DebugEvent event, uintptr_t param0, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4, u64 thread_id);
};
}

View file

@ -21,7 +21,50 @@ namespace ams::kern {
class KEventInfo : public KSlabAllocated<KEventInfo>, public util::IntrusiveListBaseNode<KEventInfo> {
public:
/* TODO: This is a placeholder definition. */
struct InfoCreateThread {
u32 thread_id;
uintptr_t tls_address;
uintptr_t entrypoint;
};
struct InfoExitProcess {
ams::svc::ProcessExitReason reason;
};
struct InfoExitThread {
ams::svc::ThreadExitReason reason;
};
struct InfoException {
ams::svc::DebugException exception_type;
s32 exception_data_count;
uintptr_t exception_address;
uintptr_t exception_data[4];
};
struct InfoSystemCall {
s64 tick;
s32 id;
};
public:
ams::svc::DebugEvent event;
u32 thread_id;
u32 flags;
bool is_attached;
bool continue_flag;
bool ignore_continue;
bool close_once;
union {
InfoCreateThread create_thread;
InfoExitProcess exit_process;
InfoExitThread exit_thread;
InfoException exception;
InfoSystemCall system_call;
} info;
KThread *debug_thread;
public:
explicit KEventInfo() : is_attached(), continue_flag(), ignore_continue() { /* ... */ }
~KEventInfo() { /* ... */ }
};
}

View file

@ -131,6 +131,8 @@ namespace ams::kern {
constexpr u64 GetProcessId() const { return this->process_id; }
constexpr State GetState() const { return this->state; }
constexpr u64 GetCoreMask() const { return this->capabilities.GetCoreMask(); }
constexpr u64 GetPriorityMask() const { return this->capabilities.GetPriorityMask(); }
@ -139,6 +141,8 @@ namespace ams::kern {
constexpr bool CheckThreadPriority(s32 prio) const { return ((1ul << prio) & this->GetPriorityMask()) != 0; }
constexpr u32 GetCreateProcessFlags() const { return this->flags; }
constexpr bool Is64Bit() const { return this->flags & ams::svc::CreateProcessFlag_Is64Bit; }
constexpr KProcessAddress GetEntryPoint() const { return this->code_address; }
@ -147,10 +151,32 @@ namespace ams::kern {
return this->is_suspended;
}
constexpr bool IsTerminated() const {
return this->state == State_Terminated;
}
constexpr bool IsAttachedToDebugger() const {
return this->attached_object != nullptr;
}
constexpr bool IsPermittedInterrupt(int32_t interrupt_id) const {
return this->capabilities.IsPermittedInterrupt(interrupt_id);
}
constexpr bool IsPermittedDebug() const {
return this->capabilities.IsPermittedDebug();
}
constexpr bool CanForceDebug() const {
return this->capabilities.CanForceDebug();
}
ThreadList &GetThreadList() { return this->thread_list; }
const ThreadList &GetThreadList() const { return this->thread_list; }
KProcess::State SetDebugObject(void *debug_object);
KEventInfo *GetJitDebugInfo();
bool EnterUserException();
bool LeaveUserException();
bool ReleaseUserException(KThread *thread);

View file

@ -311,10 +311,21 @@ namespace ams::kern {
this->priority = priority;
}
constexpr void ClearConditionVariableTree() {
constexpr void SetConditionVariable(ConditionVariableThreadTree *tree, KProcessAddress address, uintptr_t cv_key, u32 value) {
this->condvar_tree = tree;
this->condvar_key = cv_key;
this->address_key = address;
this->address_key_value = value;
}
constexpr void ClearConditionVariable() {
this->condvar_tree = nullptr;
}
constexpr bool IsWaitingForConditionVariable() const {
return this->condvar_tree != nullptr;
}
constexpr void SetupForAddressArbiterCompare(uintptr_t address, int priority) {
this->condvar_key = address;
this->priority = priority;
@ -394,6 +405,8 @@ namespace ams::kern {
constexpr KProcess *GetOwnerProcess() const { return this->parent; }
constexpr bool IsUserThread() const { return this->parent != nullptr; }
constexpr uintptr_t GetEntrypoint() const { return this->entrypoint; }
constexpr KProcessAddress GetThreadLocalRegionAddress() const { return this->tls_address; }
constexpr void *GetThreadLocalRegionHeapAddress() const { return this->tls_heap_address; }
@ -403,6 +416,9 @@ namespace ams::kern {
constexpr u16 GetUserPreemptionState() const { return *GetPointer<u16>(this->tls_address + 0x100); }
constexpr void SetKernelPreemptionState(u16 state) const { *GetPointer<u16>(this->tls_address + 0x100 + sizeof(u16)) = state; }
constexpr void SetDebugAttached() { this->debug_attached = true; }
constexpr bool IsAttachedToDebugger() const { return this->debug_attached; }
void AddCpuTime(s64 amount) {
this->cpu_time += amount;
}

View file

@ -67,6 +67,7 @@ namespace ams::kern::svc {
/* 259 */ using ::ams::svc::ResultOutOfAddressSpace;
/* 260 */ using ::ams::svc::ResultMessageTooLarge;
/* 517 */ using ::ams::svc::ResultInvalidProcessId;
/* 520 */ using ::ams::svc::ResultProcessTerminated;
}