diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 8b074db5a..017bef13c 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -98,6 +98,30 @@ std::vector> WaitTreeMutexInfo::GetChildren() cons return list; } +WaitTreeCallstack::WaitTreeCallstack(const Kernel::Thread& thread) : thread(thread) {} + +QString WaitTreeCallstack::GetText() const { + return tr("Call stack"); +} + +std::vector> WaitTreeCallstack::GetChildren() const { + std::vector> list; + + constexpr size_t BaseRegister = 29; + u64 base_pointer = thread.context.cpu_registers[BaseRegister]; + + while (base_pointer != 0) { + u64 lr = Memory::Read64(base_pointer + sizeof(u64)); + if (lr == 0) + break; + list.push_back( + std::make_unique(tr("0x%1").arg(lr - sizeof(u32), 16, 16, QChar('0')))); + base_pointer = Memory::Read64(base_pointer); + } + + return list; +} + WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {} bool WaitTreeExpandableItem::IsExpandable() const { @@ -269,6 +293,8 @@ std::vector> WaitTreeThread::GetChildren() const { thread.IsSleepingOnWaitAll())); } + list.push_back(std::make_unique(thread)); + return list; } diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 300ba9ae4..10fc9e968 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h @@ -73,6 +73,17 @@ private: Kernel::SharedPtr owner; }; +class WaitTreeCallstack : public WaitTreeExpandableItem { + Q_OBJECT +public: + explicit WaitTreeCallstack(const Kernel::Thread& thread); + QString GetText() const override; + std::vector> GetChildren() const override; + +private: + const Kernel::Thread& thread; +}; + class WaitTreeWaitObject : public WaitTreeExpandableItem { Q_OBJECT public: