kern: add handle table/process/suspend/resume debug

This commit is contained in:
Michael Scire 2020-12-09 23:44:36 -08:00
parent af259eabda
commit 8a4bf6a0a8
10 changed files with 233 additions and 18 deletions

View file

@ -25,4 +25,10 @@ namespace ams::kern::KDumpObject {
void DumpThreadCallStack();
void DumpThreadCallStack(u64 thread_id);
void DumpHandle();
void DumpHandle(u64 process_id);
void DumpProcess();
void DumpProcess(u64 process_id);
}

View file

@ -50,6 +50,8 @@ namespace ams::kern {
Result SendReply(uintptr_t message, uintptr_t buffer_size, KPhysicalAddress message_paddr);
void OnClientClosed();
void Dump();
private:
bool IsSignaledImpl() const;
void CleanupRequests();

View file

@ -46,7 +46,7 @@ namespace ams::kern {
public:
virtual void Finalize() override;
virtual bool IsSignaled() const = 0;
virtual void DebugWaiters();
virtual void DumpWaiters();
};
}

View file

@ -92,7 +92,7 @@ namespace ams::kern {
virtual uintptr_t GetPostDestroyArgument() const { return 0; }
size_t GetSlabIndex() const {
return s_slab_heap.GetIndex(static_cast<const Derived *>(this));
return s_slab_heap.GetObjectIndex(static_cast<const Derived *>(this));
}
public:
static void InitializeSlabHeap(void *memory, size_t memory_size) {

View file

@ -646,7 +646,7 @@ namespace ams::kern::arch::arm64 {
if (!ReadValue(std::addressof(temp_32), process, base_address + 0x5C)) {
return PrintAddressWithModuleName(address, has_module_name, module_name, base_address);
}
if (temp_32 != 0x94000002) { /* MOD0 */
if (temp_32 != 0x94000002) {
return PrintAddressWithModuleName(address, has_module_name, module_name, base_address);
}
if (!ReadValue(std::addressof(temp_32), process, base_address + 0x60)) {

View file

@ -28,16 +28,16 @@ namespace ams::kern::KDumpObject {
void DumpThread(KThread *thread) {
if (KProcess *process = thread->GetOwnerProcess(); process != nullptr) {
MESOSPHERE_LOG("Thread ID=%5lu pid=%3lu %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu Run=%d Ideal=%d (%d) Affinity=%016lx (%016lx)\n",
MESOSPHERE_RELEASE_LOG("Thread ID=%5lu pid=%3lu %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu Run=%d Ideal=%d (%d) Affinity=%016lx (%016lx)\n",
thread->GetId(), process->GetId(), process->GetName(), thread->GetPriority(), ThreadStates[thread->GetState()],
thread->GetKernelStackUsage(), PageSize, thread->GetActiveCore(), thread->GetIdealVirtualCore(), thread->GetIdealPhysicalCore(),
thread->GetVirtualAffinityMask(), thread->GetAffinityMask().GetAffinityMask());
MESOSPHERE_LOG(" State: 0x%04x Suspend: 0x%04x Dpc: 0x%x\n", thread->GetRawState(), thread->GetSuspendFlags(), thread->GetDpc());
MESOSPHERE_RELEASE_LOG(" State: 0x%04x Suspend: 0x%04x Dpc: 0x%x\n", thread->GetRawState(), thread->GetSuspendFlags(), thread->GetDpc());
MESOSPHERE_LOG(" TLS: %p (%p)\n", GetVoidPointer(thread->GetThreadLocalRegionAddress()), thread->GetThreadLocalRegionHeapAddress());
MESOSPHERE_RELEASE_LOG(" TLS: %p (%p)\n", GetVoidPointer(thread->GetThreadLocalRegionAddress()), thread->GetThreadLocalRegionHeapAddress());
} else {
MESOSPHERE_LOG("Thread ID=%5lu pid=%3d %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu Run=%d Ideal=%d (%d) Affinity=%016lx (%016lx)\n",
MESOSPHERE_RELEASE_LOG("Thread ID=%5lu pid=%3d %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu Run=%d Ideal=%d (%d) Affinity=%016lx (%016lx)\n",
thread->GetId(), -1, "(kernel)", thread->GetPriority(), ThreadStates[thread->GetState()],
thread->GetKernelStackUsage(), PageSize, thread->GetActiveCore(), thread->GetIdealVirtualCore(), thread->GetIdealPhysicalCore(),
thread->GetVirtualAffinityMask(), thread->GetAffinityMask().GetAffinityMask());
@ -46,21 +46,93 @@ namespace ams::kern::KDumpObject {
void DumpThreadCallStack(KThread *thread) {
if (KProcess *process = thread->GetOwnerProcess(); process != nullptr) {
MESOSPHERE_LOG("Thread ID=%5lu pid=%3lu %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu\n",
MESOSPHERE_RELEASE_LOG("Thread ID=%5lu pid=%3lu %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu\n",
thread->GetId(), process->GetId(), process->GetName(), thread->GetPriority(), ThreadStates[thread->GetState()], thread->GetKernelStackUsage(), PageSize);
KDebug::PrintRegister(thread);
KDebug::PrintBacktrace(thread);
} else {
MESOSPHERE_LOG("Thread ID=%5lu pid=%3d %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu\n",
MESOSPHERE_RELEASE_LOG("Thread ID=%5lu pid=%3d %-11s Pri=%2d %-11s KernelStack=%4zu/%4zu\n",
thread->GetId(), -1, "(kernel)", thread->GetPriority(), ThreadStates[thread->GetState()], thread->GetKernelStackUsage(), PageSize);
}
}
void DumpHandle(const KProcess::ListAccessor &accessor, KProcess *process) {
MESOSPHERE_RELEASE_LOG("Process ID=%lu (%s)\n", process->GetId(), process->GetName());
const auto end = accessor.end();
const auto &handle_table = process->GetHandleTable();
const size_t max_handles = handle_table.GetMaxCount();
for (size_t i = 0; i < max_handles; ++i) {
/* Get the object + handle. */
ams::svc::Handle handle = ams::svc::InvalidHandle;
KScopedAutoObject obj = handle_table.GetObjectByIndex(std::addressof(handle), i);
if (obj.IsNotNull()) {
if (auto *target = obj->DynamicCast<KServerSession *>(); target != nullptr) {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Client=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), std::addressof(target->GetParent()->GetClientSession()));
target->Dump();
} else if (auto *target = obj->DynamicCast<KClientSession *>(); target != nullptr) {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Server=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), std::addressof(target->GetParent()->GetServerSession()));
} else if (auto *target = obj->DynamicCast<KThread *>(); target != nullptr) {
KProcess *target_owner = target->GetOwnerProcess();
const s32 owner_pid = target_owner != nullptr ? static_cast<s32>(target_owner->GetId()) : -1;
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s ID=%d PID=%d\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), static_cast<s32>(target->GetId()), owner_pid);
} else if (auto *target = obj->DynamicCast<KProcess *>(); target != nullptr) {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s ID=%d\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), static_cast<s32>(target->GetId()));
} else if (auto *target = obj->DynamicCast<KSharedMemory *>(); target != nullptr) {
/* Find the owner. */
KProcess *target_owner = nullptr;
for (auto it = accessor.begin(); it != end; ++it) {
if (static_cast<KProcess *>(std::addressof(*it))->GetId() == target->GetOwnerProcessId()) {
target_owner = static_cast<KProcess *>(std::addressof(*it));
break;
}
}
MESOSPHERE_ASSERT(target_owner != nullptr);
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Size=%zu KB OwnerPID=%d (%s)\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), target->GetSize() / 1_KB, static_cast<s32>(target_owner->GetId()), target_owner->GetName());
} else if (auto *target = obj->DynamicCast<KTransferMemory *>(); target != nullptr) {
KProcess *target_owner = target->GetOwner();
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s OwnerPID=%d (%s) OwnerAddress=%lx Size=%zu KB\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), static_cast<s32>(target_owner->GetId()), target_owner->GetName(), GetInteger(target->GetSourceAddress()), target->GetSize() / 1_KB);
} else if (auto *target = obj->DynamicCast<KCodeMemory *>(); target != nullptr) {
KProcess *target_owner = target->GetOwner();
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s OwnerPID=%d (%s) OwnerAddress=%lx Size=%zu KB\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), static_cast<s32>(target_owner->GetId()), target_owner->GetName(), GetInteger(target->GetSourceAddress()), target->GetSize() / 1_KB);
} else if (auto *target = obj->DynamicCast<KInterruptEvent *>(); target != nullptr) {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s irq=%d\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), target->GetInterruptId());
} else if (auto *target = obj->DynamicCast<KWritableEvent *>(); target != nullptr) {
if (KEvent *event = target->GetParent(); event != nullptr) {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Pair=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), std::addressof(event->GetReadableEvent()));
} else {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName());
}
} else if (auto *target = obj->DynamicCast<KReadableEvent *>(); target != nullptr) {
if (KEvent *event = target->GetParent(); event != nullptr) {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s Pair=%p\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName(), std::addressof(event->GetWritableEvent()));
} else {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName());
}
} else {
MESOSPHERE_RELEASE_LOG("Handle %08x Obj=%p Ref=%d Type=%s\n", handle, obj.GetPointerUnsafe(), obj->GetReferenceCount() - 1, obj->GetTypeName());
}
if (auto *sync = obj->DynamicCast<KSynchronizationObject *>(); sync != nullptr) {
sync->DumpWaiters();
}
}
}
MESOSPHERE_RELEASE_LOG("%zu(max %zu)/%zu used.\n", handle_table.GetCount(), max_handles, handle_table.GetTableSize());
MESOSPHERE_RELEASE_LOG("\n\n");
}
void DumpProcess(KProcess *process) {
MESOSPHERE_RELEASE_LOG("Process ID=%3lu index=%3zu State=%d (%s)\n", process->GetId(), process->GetSlabIndex(), process->GetState(), process->GetName());
}
}
void DumpThread() {
MESOSPHERE_LOG("Dump Thread\n");
MESOSPHERE_RELEASE_LOG("Dump Thread\n");
{
/* Lock the list. */
@ -73,11 +145,11 @@ namespace ams::kern::KDumpObject {
}
}
MESOSPHERE_LOG("\n");
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpThread(u64 thread_id) {
MESOSPHERE_LOG("Dump Thread\n");
MESOSPHERE_RELEASE_LOG("Dump Thread\n");
{
/* Find and dump the target thread. */
@ -87,11 +159,11 @@ namespace ams::kern::KDumpObject {
}
}
MESOSPHERE_LOG("\n");
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpThreadCallStack() {
MESOSPHERE_LOG("Dump Thread\n");
MESOSPHERE_RELEASE_LOG("Dump Thread\n");
{
/* Lock the list. */
@ -104,11 +176,11 @@ namespace ams::kern::KDumpObject {
}
}
MESOSPHERE_LOG("\n");
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpThreadCallStack(u64 thread_id) {
MESOSPHERE_LOG("Dump Thread\n");
MESOSPHERE_RELEASE_LOG("Dump Thread\n");
{
/* Find and dump the target thread. */
@ -118,7 +190,72 @@ namespace ams::kern::KDumpObject {
}
}
MESOSPHERE_LOG("\n");
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpHandle() {
MESOSPHERE_RELEASE_LOG("Dump Handle\n");
{
/* Lock the list. */
KProcess::ListAccessor accessor;
const auto end = accessor.end();
/* Dump each process. */
for (auto it = accessor.begin(); it != end; ++it) {
DumpHandle(accessor, static_cast<KProcess *>(std::addressof(*it)));
}
}
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpHandle(u64 process_id) {
MESOSPHERE_RELEASE_LOG("Dump Handle\n");
{
/* Find and dump the target process. */
if (KProcess *process = KProcess::GetProcessFromId(process_id); process != nullptr) {
ON_SCOPE_EXIT { process->Close(); };
/* Lock the list. */
KProcess::ListAccessor accessor;
DumpHandle(accessor, process);
}
}
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpProcess() {
MESOSPHERE_RELEASE_LOG("Dump Process\n");
{
/* Lock the list. */
KProcess::ListAccessor accessor;
const auto end = accessor.end();
/* Dump each process. */
for (auto it = accessor.begin(); it != end; ++it) {
DumpProcess(static_cast<KProcess *>(std::addressof(*it)));
}
}
MESOSPHERE_RELEASE_LOG("\n");
}
void DumpProcess(u64 process_id) {
MESOSPHERE_RELEASE_LOG("Dump Process\n");
{
/* Find and dump the target process. */
if (KProcess *process = KProcess::GetProcessFromId(process_id); process != nullptr) {
ON_SCOPE_EXIT { process->Close(); };
DumpProcess(process);
}
}
MESOSPHERE_RELEASE_LOG("\n");
}
}

View file

@ -1367,4 +1367,36 @@ namespace ams::kern {
#pragma GCC pop_options
void KServerSession::Dump() {
MESOSPHERE_ASSERT_THIS();
KScopedLightLock lk(this->lock);
{
KScopedSchedulerLock sl;
MESOSPHERE_RELEASE_LOG("Dump Session %p\n", this);
/* Dump current request. */
bool has_request = false;
if (this->current_request != nullptr) {
KThread *thread = this->current_request->GetThread();
const s32 thread_id = thread != nullptr ? static_cast<s32>(thread->GetId()) : -1;
MESOSPHERE_RELEASE_LOG(" CurrentReq %p Thread=%p ID=%d\n", this->current_request, thread, thread_id);
has_request = true;
}
/* Dump all rqeuests in list. */
for (auto it = this->request_list.begin(); it != this->request_list.end(); ++it) {
KThread *thread = it->GetThread();
const s32 thread_id = thread != nullptr ? static_cast<s32>(thread->GetId()) : -1;
MESOSPHERE_RELEASE_LOG(" Req %p Thread=%p ID=%d\n", this->current_request, thread, thread_id);
has_request = true;
}
/* If we didn't have any requests, print so. */
if (!has_request) {
MESOSPHERE_RELEASE_LOG(" None\n");
}
}
}
}

View file

@ -148,7 +148,7 @@ namespace ams::kern {
}
}
void KSynchronizationObject::DebugWaiters() {
void KSynchronizationObject::DumpWaiters() {
MESOSPHERE_ASSERT_THIS();
/* If debugging, dump the list of waiters. */

View file

@ -41,6 +41,38 @@ namespace ams::kern::svc {
KDumpObject::DumpThreadCallStack(arg0);
}
break;
case ams::svc::KernelDebugType_Handle:
if (arg0 == static_cast<u64>(-1)) {
KDumpObject::DumpHandle();
} else {
KDumpObject::DumpHandle(arg0);
}
break;
case ams::svc::KernelDebugType_Process:
if (arg0 == static_cast<u64>(-1)) {
KDumpObject::DumpProcess();
} else {
KDumpObject::DumpProcess(arg0);
}
break;
case ams::svc::KernelDebugType_SuspendProcess:
if (KProcess *process = KProcess::GetProcessFromId(arg0); process != nullptr) {
ON_SCOPE_EXIT { process->Close(); };
if (R_SUCCEEDED(process->SetActivity(ams::svc::ProcessActivity_Paused))) {
MESOSPHERE_RELEASE_LOG("Suspend Process ID=%3lu\n", process->GetId());
}
}
break;
case ams::svc::KernelDebugType_ResumeProcess:
if (KProcess *process = KProcess::GetProcessFromId(arg0); process != nullptr) {
ON_SCOPE_EXIT { process->Close(); };
if (R_SUCCEEDED(process->SetActivity(ams::svc::ProcessActivity_Runnable))) {
MESOSPHERE_RELEASE_LOG("Resume Process ID=%3lu\n", process->GetId());
}
}
break;
default:
break;
}

View file

@ -472,6 +472,12 @@ namespace ams::svc {
enum KernelDebugType : u32 {
KernelDebugType_Thread = 0,
KernelDebugType_ThreadCallStack = 1,
KernelDebugType_Handle = 3,
KernelDebugType_Process = 7,
KernelDebugType_SuspendProcess = 8,
KernelDebugType_ResumeProcess = 9,
};
enum KernelTraceState : u32 {