diff options
| author | 2020-03-20 14:05:47 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:54 -0400 | |
| commit | 7b18174eef70feb434f9319a57a6cfbe362730e3 (patch) | |
| tree | 47f3d88e31de2bb1551440a1b0c17a2fae4960f3 /src | |
| parent | SVC/ARM: Correct svcSendSyncRequest and cache ticks on arm interface. (diff) | |
| download | yuzu-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.cpp | 57 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.h | 3 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 25 |
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 | ||
| 140 | constexpr u64 SEGMENT_BASE = 0x7100000000ull; | 140 | constexpr u64 SEGMENT_BASE = 0x7100000000ull; |
| 141 | 141 | ||
| 142 | std::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 | |||
| 142 | std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const { | 199 | std::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 { | |||
| 116 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const { | 119 | std::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; |