summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Debug/OSThread.cpp
diff options
context:
space:
mode:
authorSepalani <sepalani@hotmail.fr>2020-03-21 11:48:49 +0400
committerSepalani <sepalani@hotmail.fr>2020-05-03 20:48:30 +0400
commit39d34e133f0fe6a11db11e523cfbeaf9faf9b2a1 (patch)
tree4921345c657fa310610cbb6d19eae5794e754024 /Source/Core/Common/Debug/OSThread.cpp
parent9ffa72ad1fb8574ecda9e120d8a7fb930d053b01 (diff)
Debugger: Add a Thread widget
DebugInterface: Add GetThreads WatchWidget: Update widget on AddWatch
Diffstat (limited to 'Source/Core/Common/Debug/OSThread.cpp')
-rw-r--r--Source/Core/Common/Debug/OSThread.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/Source/Core/Common/Debug/OSThread.cpp b/Source/Core/Common/Debug/OSThread.cpp
new file mode 100644
index 0000000000..809e5adccd
--- /dev/null
+++ b/Source/Core/Common/Debug/OSThread.cpp
@@ -0,0 +1,204 @@
+// Copyright 2020 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "Common/Debug/OSThread.h"
+
+#include <algorithm>
+#include <fmt/format.h>
+
+#include "Core/PowerPC/MMU.h"
+
+// Context offsets based on the following functions:
+// - OSSaveContext
+// - OSSaveFPUContext
+// - OSDumpContext
+// - OSClearContext
+// - OSExceptionVector
+void Common::Debug::OSContext::Read(u32 addr)
+{
+ for (std::size_t i = 0; i < gpr.size(); i++)
+ gpr[i] = PowerPC::HostRead_U32(addr + u32(i * sizeof(int)));
+ cr = PowerPC::HostRead_U32(addr + 0x80);
+ lr = PowerPC::HostRead_U32(addr + 0x84);
+ ctr = PowerPC::HostRead_U32(addr + 0x88);
+ xer = PowerPC::HostRead_U32(addr + 0x8C);
+ for (std::size_t i = 0; i < fpr.size(); i++)
+ fpr[i] = PowerPC::HostRead_F64(addr + 0x90 + u32(i * sizeof(double)));
+ fpscr = PowerPC::HostRead_U64(addr + 0x190);
+ srr0 = PowerPC::HostRead_U32(addr + 0x198);
+ srr1 = PowerPC::HostRead_U32(addr + 0x19c);
+ dummy = PowerPC::HostRead_U16(addr + 0x1a0);
+ state = static_cast<OSContext::State>(PowerPC::HostRead_U16(addr + 0x1a2));
+ for (std::size_t i = 0; i < gqr.size(); i++)
+ gqr[i] = PowerPC::HostRead_U32(addr + 0x1a4 + u32(i * sizeof(int)));
+ psf_padding = 0;
+ for (std::size_t i = 0; i < psf.size(); i++)
+ psf[i] = PowerPC::HostRead_F64(addr + 0x1c8 + u32(i * sizeof(double)));
+}
+
+// Mutex offsets based on the following functions:
+// - OSInitMutex
+// - OSLockMutex
+// - __OSUnlockAllMutex
+void Common::Debug::OSMutex::Read(u32 addr)
+{
+ thread_queue.head = PowerPC::HostRead_U32(addr);
+ thread_queue.tail = PowerPC::HostRead_U32(addr + 0x4);
+ owner_addr = PowerPC::HostRead_U32(addr + 0x8);
+ lock_count = PowerPC::HostRead_U32(addr + 0xc);
+ link.next = PowerPC::HostRead_U32(addr + 0x10);
+ link.prev = PowerPC::HostRead_U32(addr + 0x14);
+}
+
+// Thread offsets based on the following functions:
+// - OSCreateThread
+// - OSIsThreadTerminated
+// - OSJoinThread
+// - OSSuspendThread
+// - OSSetPriority
+// - OSExitThread
+// - OSLockMutex
+// - __OSUnlockAllMutex
+// - __OSThreadInit
+// - OSSetThreadSpecific
+// - SOInit (for errno)
+void Common::Debug::OSThread::Read(u32 addr)
+{
+ context.Read(addr);
+ state = PowerPC::HostRead_U16(addr + 0x2c8);
+ is_detached = PowerPC::HostRead_U16(addr + 0x2ca);
+ suspend = PowerPC::HostRead_U32(addr + 0x2cc);
+ effective_priority = PowerPC::HostRead_U32(addr + 0x2d0);
+ base_priority = PowerPC::HostRead_U32(addr + 0x2d4);
+ exit_code_addr = PowerPC::HostRead_U32(addr + 0x2d8);
+
+ queue_addr = PowerPC::HostRead_U32(addr + 0x2dc);
+ queue_link.next = PowerPC::HostRead_U32(addr + 0x2e0);
+ queue_link.prev = PowerPC::HostRead_U32(addr + 0x2e4);
+
+ join_queue.head = PowerPC::HostRead_U32(addr + 0x2e8);
+ join_queue.tail = PowerPC::HostRead_U32(addr + 0x2ec);
+
+ mutex_addr = PowerPC::HostRead_U32(addr + 0x2f0);
+ mutex_queue.head = PowerPC::HostRead_U32(addr + 0x2f4);
+ mutex_queue.tail = PowerPC::HostRead_U32(addr + 0x2f8);
+
+ thread_link.next = PowerPC::HostRead_U32(addr + 0x2fc);
+ thread_link.prev = PowerPC::HostRead_U32(addr + 0x300);
+
+ stack_addr = PowerPC::HostRead_U32(addr + 0x304);
+ stack_end = PowerPC::HostRead_U32(addr + 0x308);
+ error = PowerPC::HostRead_U32(addr + 0x30c);
+ specific[0] = PowerPC::HostRead_U32(addr + 0x310);
+ specific[1] = PowerPC::HostRead_U32(addr + 0x314);
+}
+
+bool Common::Debug::OSThread::IsValid() const
+{
+ return PowerPC::HostIsRAMAddress(stack_end) && PowerPC::HostRead_U32(stack_end) == STACK_MAGIC;
+}
+
+Common::Debug::OSThreadView::OSThreadView(u32 addr)
+{
+ m_address = addr;
+ m_thread.Read(addr);
+}
+
+const Common::Debug::OSThread& Common::Debug::OSThreadView::Data() const
+{
+ return m_thread;
+}
+
+Common::Debug::PartialContext Common::Debug::OSThreadView::GetContext() const
+{
+ PartialContext context;
+
+ if (!IsValid())
+ return context;
+
+ context.gpr = m_thread.context.gpr;
+ context.cr = m_thread.context.cr;
+ context.lr = m_thread.context.lr;
+ context.ctr = m_thread.context.ctr;
+ context.xer = m_thread.context.xer;
+ context.fpr = m_thread.context.fpr;
+ context.fpscr = m_thread.context.fpscr;
+ context.srr0 = m_thread.context.srr0;
+ context.srr1 = m_thread.context.srr1;
+ context.dummy = m_thread.context.dummy;
+ context.state = static_cast<u16>(m_thread.context.state);
+ context.gqr = m_thread.context.gqr;
+ context.psf = m_thread.context.psf;
+
+ return context;
+}
+
+u32 Common::Debug::OSThreadView::GetAddress() const
+{
+ return m_address;
+}
+
+u16 Common::Debug::OSThreadView::GetState() const
+{
+ return m_thread.state;
+}
+
+bool Common::Debug::OSThreadView::IsSuspended() const
+{
+ return m_thread.suspend > 0;
+}
+
+bool Common::Debug::OSThreadView::IsDetached() const
+{
+ return m_thread.is_detached != 0;
+}
+
+s32 Common::Debug::OSThreadView::GetBasePriority() const
+{
+ return m_thread.base_priority;
+}
+
+s32 Common::Debug::OSThreadView::GetEffectivePriority() const
+{
+ return m_thread.effective_priority;
+}
+
+u32 Common::Debug::OSThreadView::GetStackStart() const
+{
+ return m_thread.stack_addr;
+}
+
+u32 Common::Debug::OSThreadView::GetStackEnd() const
+{
+ return m_thread.stack_end;
+}
+
+std::size_t Common::Debug::OSThreadView::GetStackSize() const
+{
+ return GetStackStart() - GetStackEnd();
+}
+
+s32 Common::Debug::OSThreadView::GetErrno() const
+{
+ return m_thread.error;
+}
+
+std::string Common::Debug::OSThreadView::GetSpecific() const
+{
+ std::string specific;
+
+ for (u32 addr : m_thread.specific)
+ {
+ if (!PowerPC::HostIsRAMAddress(addr))
+ break;
+ specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::HostGetString(addr));
+ }
+
+ return specific;
+}
+
+bool Common::Debug::OSThreadView::IsValid() const
+{
+ return m_thread.IsValid();
+}