summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/arm/arm_interface.cpp97
-rw-r--r--src/core/arm/arm_interface.h18
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp19
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h8
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp38
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h8
6 files changed, 98 insertions, 90 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 08bf1201d..2a9390e26 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -14,96 +14,28 @@
14#include "core/loader/loader.h" 14#include "core/loader/loader.h"
15#include "core/memory.h" 15#include "core/memory.h"
16 16
17#include "core/arm/dynarmic/arm_dynarmic_32.h"
18#include "core/arm/dynarmic/arm_dynarmic_64.h"
19
17namespace Core { 20namespace Core {
18 21
19constexpr u64 SEGMENT_BASE = 0x7100000000ull; 22constexpr u64 SEGMENT_BASE = 0x7100000000ull;
20 23
21std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext( 24std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
22 System& system, const ThreadContext64& ctx) { 25 Core::System& system, const ARM_Interface::ThreadContext32& ctx) {
23 std::vector<BacktraceEntry> out; 26 return ARM_Dynarmic_32::GetBacktraceFromContext(system, ctx);
24 auto& memory = system.Memory();
25
26 auto fp = ctx.cpu_registers[29];
27 auto lr = ctx.cpu_registers[30];
28 while (true) {
29 out.push_back({
30 .module = "",
31 .address = 0,
32 .original_address = lr,
33 .offset = 0,
34 .name = {},
35 });
36
37 if (fp == 0) {
38 break;
39 }
40
41 lr = memory.Read64(fp + 8) - 4;
42 fp = memory.Read64(fp);
43 }
44
45 std::map<VAddr, std::string> modules;
46 auto& loader{system.GetAppLoader()};
47 if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
48 return {};
49 }
50
51 std::map<std::string, Symbols::Symbols> symbols;
52 for (const auto& module : modules) {
53 symbols.insert_or_assign(module.second,
54 Symbols::GetSymbols(module.first, system.Memory(),
55 system.CurrentProcess()->Is64BitProcess()));
56 }
57
58 for (auto& entry : out) {
59 VAddr base = 0;
60 for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
61 const auto& module{*iter};
62 if (entry.original_address >= module.first) {
63 entry.module = module.second;
64 base = module.first;
65 break;
66 }
67 }
68
69 entry.offset = entry.original_address - base;
70 entry.address = SEGMENT_BASE + entry.offset;
71
72 if (entry.module.empty())
73 entry.module = "unknown";
74
75 const auto symbol_set = symbols.find(entry.module);
76 if (symbol_set != symbols.end()) {
77 const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset);
78 if (symbol.has_value()) {
79 // TODO(DarkLordZach): Add demangling of symbol names.
80 entry.name = *symbol;
81 }
82 }
83 }
84
85 return out;
86} 27}
87 28
88std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const { 29std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
89 std::vector<BacktraceEntry> out; 30 Core::System& system, const ARM_Interface::ThreadContext64& ctx) {
90 auto& memory = system.Memory(); 31 return ARM_Dynarmic_64::GetBacktraceFromContext(system, ctx);
91 32}
92 auto fp = GetReg(29);
93 auto lr = GetReg(30);
94 while (true) {
95 out.push_back({"", 0, lr, 0, ""});
96 if (!fp) {
97 break;
98 }
99 lr = memory.Read64(fp + 8) - 4;
100 fp = memory.Read64(fp);
101 }
102 33
34void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out) {
103 std::map<VAddr, std::string> modules; 35 std::map<VAddr, std::string> modules;
104 auto& loader{system.GetAppLoader()}; 36 auto& loader{system.GetAppLoader()};
105 if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) { 37 if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
106 return {}; 38 return;
107 } 39 }
108 40
109 std::map<std::string, Symbols::Symbols> symbols; 41 std::map<std::string, Symbols::Symbols> symbols;
@@ -127,8 +59,9 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
127 entry.offset = entry.original_address - base; 59 entry.offset = entry.original_address - base;
128 entry.address = SEGMENT_BASE + entry.offset; 60 entry.address = SEGMENT_BASE + entry.offset;
129 61
130 if (entry.module.empty()) 62 if (entry.module.empty()) {
131 entry.module = "unknown"; 63 entry.module = "unknown";
64 }
132 65
133 const auto symbol_set = symbols.find(entry.module); 66 const auto symbol_set = symbols.find(entry.module);
134 if (symbol_set != symbols.end()) { 67 if (symbol_set != symbols.end()) {
@@ -139,12 +72,10 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
139 } 72 }
140 } 73 }
141 } 74 }
142
143 return out;
144} 75}
145 76
146void ARM_Interface::LogBacktrace() const { 77void ARM_Interface::LogBacktrace() const {
147 const VAddr sp = GetReg(13); 78 const VAddr sp = GetSP();
148 const VAddr pc = GetPC(); 79 const VAddr pc = GetPC();
149 LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc); 80 LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
150 LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address", 81 LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address",
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index dce2f4195..bcec4b3b8 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -101,6 +101,12 @@ public:
101 virtual u64 GetPC() const = 0; 101 virtual u64 GetPC() const = 0;
102 102
103 /** 103 /**
104 * Get the current Stack Pointer
105 * @return Returns current SP
106 */
107 virtual u64 GetSP() const = 0;
108
109 /**
104 * Get an ARM register 110 * Get an ARM register
105 * @param index Register index 111 * @param index Register index
106 * @return Returns the value in the register 112 * @return Returns the value in the register
@@ -183,16 +189,12 @@ public:
183 }; 189 };
184 190
185 static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system, 191 static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
192 const ThreadContext32& ctx);
193 static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
186 const ThreadContext64& ctx); 194 const ThreadContext64& ctx);
187 195
188 std::vector<BacktraceEntry> GetBacktrace() const; 196 virtual std::vector<BacktraceEntry> GetBacktrace() const = 0;
189 197
190 /// fp (= r29) points to the last frame record.
191 /// Note that this is the frame record for the *previous* frame, not the current one.
192 /// Note we need to subtract 4 from our last read to get the proper address
193 /// Frame records are two words long:
194 /// fp+0 : pointer to previous frame record
195 /// fp+8 : value of lr for frame
196 void LogBacktrace() const; 198 void LogBacktrace() const;
197 199
198protected: 200protected:
@@ -200,6 +202,8 @@ protected:
200 System& system; 202 System& system;
201 CPUInterrupts& interrupt_handlers; 203 CPUInterrupts& interrupt_handlers;
202 bool uses_wall_clock; 204 bool uses_wall_clock;
205
206 static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out);
203}; 207};
204 208
205} // namespace Core 209} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 5de4384db..da5659046 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -268,6 +268,10 @@ u64 ARM_Dynarmic_32::GetPC() const {
268 return jit.load()->Regs()[15]; 268 return jit.load()->Regs()[15];
269} 269}
270 270
271u64 ARM_Dynarmic_32::GetSP() const {
272 return jit.load()->Regs()[13];
273}
274
271u64 ARM_Dynarmic_32::GetReg(int index) const { 275u64 ARM_Dynarmic_32::GetReg(int index) const {
272 return jit.load()->Regs()[index]; 276 return jit.load()->Regs()[index];
273} 277}
@@ -362,4 +366,19 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
362 jit_cache.emplace(key, std::move(new_jit)); 366 jit_cache.emplace(key, std::move(new_jit));
363} 367}
364 368
369std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system,
370 u64 sp, u64 lr) {
371 // No way to get accurate stack traces in A32 yet
372 return {};
373}
374
375std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext(
376 System& system, const ThreadContext32& ctx) {
377 return GetBacktrace(system, ctx.cpu_registers[13], ctx.cpu_registers[14]);
378}
379
380std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const {
381 return GetBacktrace(system, GetReg(13), GetReg(14));
382}
383
365} // namespace Core 384} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 684937353..1b628f94d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -35,6 +35,7 @@ public:
35 35
36 void SetPC(u64 pc) override; 36 void SetPC(u64 pc) override;
37 u64 GetPC() const override; 37 u64 GetPC() const override;
38 u64 GetSP() const override;
38 u64 GetReg(int index) const override; 39 u64 GetReg(int index) const override;
39 void SetReg(int index, u64 value) override; 40 void SetReg(int index, u64 value) override;
40 u128 GetVectorReg(int index) const override; 41 u128 GetVectorReg(int index) const override;
@@ -66,9 +67,16 @@ public:
66 void PageTableChanged(Common::PageTable& new_page_table, 67 void PageTableChanged(Common::PageTable& new_page_table,
67 std::size_t new_address_space_size_in_bits) override; 68 std::size_t new_address_space_size_in_bits) override;
68 69
70 static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
71 const ThreadContext32& ctx);
72
73 std::vector<BacktraceEntry> GetBacktrace() const override;
74
69private: 75private:
70 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; 76 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const;
71 77
78 static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 sp, u64 lr);
79
72 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; 80 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
73 using JitCacheType = 81 using JitCacheType =
74 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>; 82 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index ae0b158c2..871d9d10e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -328,6 +328,10 @@ u64 ARM_Dynarmic_64::GetPC() const {
328 return jit.load()->GetPC(); 328 return jit.load()->GetPC();
329} 329}
330 330
331u64 ARM_Dynarmic_64::GetSP() const {
332 return jit.load()->GetSP();
333}
334
331u64 ARM_Dynarmic_64::GetReg(int index) const { 335u64 ARM_Dynarmic_64::GetReg(int index) const {
332 return jit.load()->GetRegister(index); 336 return jit.load()->GetRegister(index);
333} 337}
@@ -430,4 +434,38 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
430 jit_cache.emplace(key, std::move(new_jit)); 434 jit_cache.emplace(key, std::move(new_jit));
431} 435}
432 436
437std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system,
438 u64 fp, u64 lr) {
439 std::vector<BacktraceEntry> out;
440 auto& memory = system.Memory();
441
442 // fp (= r29) points to the last frame record.
443 // Note that this is the frame record for the *previous* frame, not the current one.
444 // Note we need to subtract 4 from our last read to get the proper address
445 // Frame records are two words long:
446 // fp+0 : pointer to previous frame record
447 // fp+8 : value of lr for frame
448 while (true) {
449 out.push_back({"", 0, lr, 0, ""});
450 if (!fp) {
451 break;
452 }
453 lr = memory.Read64(fp + 8) - 4;
454 fp = memory.Read64(fp);
455 }
456
457 SymbolicateBacktrace(system, out);
458
459 return out;
460}
461
462std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext(
463 System& system, const ThreadContext64& ctx) {
464 return GetBacktrace(system, ctx.cpu_registers[29], ctx.cpu_registers[30]);
465}
466
467std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const {
468 return GetBacktrace(system, GetReg(29), GetReg(30));
469}
470
433} // namespace Core 471} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 86018f196..78773e293 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -33,6 +33,7 @@ public:
33 33
34 void SetPC(u64 pc) override; 34 void SetPC(u64 pc) override;
35 u64 GetPC() const override; 35 u64 GetPC() const override;
36 u64 GetSP() const override;
36 u64 GetReg(int index) const override; 37 u64 GetReg(int index) const override;
37 void SetReg(int index, u64 value) override; 38 void SetReg(int index, u64 value) override;
38 u128 GetVectorReg(int index) const override; 39 u128 GetVectorReg(int index) const override;
@@ -60,10 +61,17 @@ public:
60 void PageTableChanged(Common::PageTable& new_page_table, 61 void PageTableChanged(Common::PageTable& new_page_table,
61 std::size_t new_address_space_size_in_bits) override; 62 std::size_t new_address_space_size_in_bits) override;
62 63
64 static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
65 const ThreadContext64& ctx);
66
67 std::vector<BacktraceEntry> GetBacktrace() const override;
68
63private: 69private:
64 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, 70 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
65 std::size_t address_space_bits) const; 71 std::size_t address_space_bits) const;
66 72
73 static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr);
74
67 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; 75 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
68 using JitCacheType = 76 using JitCacheType =
69 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>; 77 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;