summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-03-20 14:05:47 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:54 -0400
commit7b18174eef70feb434f9319a57a6cfbe362730e3 (patch)
tree47f3d88e31de2bb1551440a1b0c17a2fae4960f3 /src
parentSVC/ARM: Correct svcSendSyncRequest and cache ticks on arm interface. (diff)
downloadyuzu-7b18174eef70feb434f9319a57a6cfbe362730e3.tar.gz
yuzu-7b18174eef70feb434f9319a57a6cfbe362730e3.tar.xz
yuzu-7b18174eef70feb434f9319a57a6cfbe362730e3.zip
ARM/WaitTree: Better track the CallStack for each thread.
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/arm_interface.cpp57
-rw-r--r--src/core/arm/arm_interface.h3
-rw-r--r--src/yuzu/debugger/wait_tree.cpp25
3 files changed, 74 insertions, 11 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index d079a1bc8..d2295ed90 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -139,6 +139,63 @@ std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr func_addr
139 139
140constexpr u64 SEGMENT_BASE = 0x7100000000ull; 140constexpr u64 SEGMENT_BASE = 0x7100000000ull;
141 141
142std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
143 System& system, const ThreadContext64& ctx) {
144 std::vector<BacktraceEntry> out;
145 auto& memory = system.Memory();
146
147 auto fp = ctx.cpu_registers[29];
148 auto lr = ctx.cpu_registers[30];
149 while (true) {
150 out.push_back({"", 0, lr, 0});
151 if (!fp) {
152 break;
153 }
154 lr = memory.Read64(fp + 8) - 4;
155 fp = memory.Read64(fp);
156 }
157
158 std::map<VAddr, std::string> modules;
159 auto& loader{system.GetAppLoader()};
160 if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
161 return {};
162 }
163
164 std::map<std::string, Symbols> symbols;
165 for (const auto& module : modules) {
166 symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
167 }
168
169 for (auto& entry : out) {
170 VAddr base = 0;
171 for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
172 const auto& module{*iter};
173 if (entry.original_address >= module.first) {
174 entry.module = module.second;
175 base = module.first;
176 break;
177 }
178 }
179
180 entry.offset = entry.original_address - base;
181 entry.address = SEGMENT_BASE + entry.offset;
182
183 if (entry.module.empty())
184 entry.module = "unknown";
185
186 const auto symbol_set = symbols.find(entry.module);
187 if (symbol_set != symbols.end()) {
188 const auto symbol = GetSymbolName(symbol_set->second, entry.offset);
189 if (symbol.has_value()) {
190 // TODO(DarkLordZach): Add demangling of symbol names.
191 entry.name = *symbol;
192 }
193 }
194 }
195
196 return out;
197}
198
142std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const { 199std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
143 std::vector<BacktraceEntry> out; 200 std::vector<BacktraceEntry> out;
144 auto& memory = system.Memory(); 201 auto& memory = system.Memory();
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 87a1c29cc..e701ddf21 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -164,6 +164,9 @@ public:
164 std::string name; 164 std::string name;
165 }; 165 };
166 166
167 static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
168 const ThreadContext64& ctx);
169
167 std::vector<BacktraceEntry> GetBacktrace() const; 170 std::vector<BacktraceEntry> GetBacktrace() const;
168 171
169 /// fp (= r29) points to the last frame record. 172 /// fp (= r29) points to the last frame record.
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index fa091f457..d2dbb259c 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -2,10 +2,13 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <fmt/format.h>
6
5#include "yuzu/debugger/wait_tree.h" 7#include "yuzu/debugger/wait_tree.h"
6#include "yuzu/util/util.h" 8#include "yuzu/util/util.h"
7 9
8#include "common/assert.h" 10#include "common/assert.h"
11#include "core/arm/arm_interface.h"
9#include "core/core.h" 12#include "core/core.h"
10#include "core/hle/kernel/handle_table.h" 13#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/mutex.h" 14#include "core/hle/kernel/mutex.h"
@@ -116,20 +119,20 @@ QString WaitTreeCallstack::GetText() const {
116std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const { 119std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {
117 std::vector<std::unique_ptr<WaitTreeItem>> list; 120 std::vector<std::unique_ptr<WaitTreeItem>> list;
118 121
119 constexpr std::size_t BaseRegister = 29; 122 if (thread.IsHLEThread()) {
120 auto& memory = Core::System::GetInstance().Memory(); 123 return list;
121 u64 base_pointer = thread.GetContext64().cpu_registers[BaseRegister]; 124 }
122 125
123 while (base_pointer != 0) { 126 if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64BitProcess()) {
124 const u64 lr = memory.Read64(base_pointer + sizeof(u64)); 127 return list;
125 if (lr == 0) { 128 }
126 break;
127 }
128 129
129 list.push_back(std::make_unique<WaitTreeText>( 130 auto backtrace = Core::ARM_Interface::GetBacktraceFromContext(Core::System::GetInstance(), thread.GetContext64());
130 tr("0x%1").arg(lr - sizeof(u32), 16, 16, QLatin1Char{'0'})));
131 131
132 base_pointer = memory.Read64(base_pointer); 132 for (auto& entry : backtrace) {
133 std::string s = fmt::format("{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
134 entry.original_address, entry.offset, entry.name);
135 list.push_back(std::make_unique<WaitTreeText>(QString::fromStdString(s)));
133 } 136 }
134 137
135 return list; 138 return list;