diff options
Diffstat (limited to 'Source/Core/Common/Debug/OSThread.cpp')
| -rw-r--r-- | Source/Core/Common/Debug/OSThread.cpp | 204 |
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(); +} |
