diff options
| author | 2022-07-07 23:49:54 -0400 | |
|---|---|---|
| committer | 2022-07-07 23:49:54 -0400 | |
| commit | 313f047f974249c0fa004056ced3f18a8c61eae4 (patch) | |
| tree | 56d70869ae85bd0dce17923259d25e96be3c98a9 | |
| parent | Merge pull request #8502 from liamwhite/end-wait (diff) | |
| parent | core/arm: better support for backtrace generation (diff) | |
| download | yuzu-313f047f974249c0fa004056ced3f18a8c61eae4.tar.gz yuzu-313f047f974249c0fa004056ced3f18a8c61eae4.tar.xz yuzu-313f047f974249c0fa004056ced3f18a8c61eae4.zip | |
Merge pull request #8501 from liamwhite/backtrace-again
core/arm: better support for backtrace generation
| -rw-r--r-- | src/core/arm/arm_interface.cpp | 15 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 30 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 2 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 17 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 2 |
5 files changed, 51 insertions, 15 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 0efc3732f..cef79b245 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #ifndef _MSC_VER | ||
| 5 | #include <cxxabi.h> | ||
| 6 | #endif | ||
| 7 | |||
| 4 | #include <map> | 8 | #include <map> |
| 5 | #include <optional> | 9 | #include <optional> |
| 6 | #include "common/bit_field.h" | 10 | #include "common/bit_field.h" |
| @@ -68,8 +72,19 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt | |||
| 68 | if (symbol_set != symbols.end()) { | 72 | if (symbol_set != symbols.end()) { |
| 69 | const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset); | 73 | const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset); |
| 70 | if (symbol.has_value()) { | 74 | if (symbol.has_value()) { |
| 75 | #ifdef _MSC_VER | ||
| 71 | // TODO(DarkLordZach): Add demangling of symbol names. | 76 | // TODO(DarkLordZach): Add demangling of symbol names. |
| 72 | entry.name = *symbol; | 77 | entry.name = *symbol; |
| 78 | #else | ||
| 79 | int status{-1}; | ||
| 80 | char* demangled{abi::__cxa_demangle(symbol->c_str(), nullptr, nullptr, &status)}; | ||
| 81 | if (status == 0 && demangled != nullptr) { | ||
| 82 | entry.name = demangled; | ||
| 83 | std::free(demangled); | ||
| 84 | } else { | ||
| 85 | entry.name = *symbol; | ||
| 86 | } | ||
| 87 | #endif | ||
| 73 | } | 88 | } |
| 74 | } | 89 | } |
| 75 | } | 90 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 10cf72a45..1be5fe1c1 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -427,18 +427,38 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, | |||
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, | 429 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, |
| 430 | u64 sp, u64 lr) { | 430 | u64 fp, u64 lr, u64 pc) { |
| 431 | // No way to get accurate stack traces in A32 yet | 431 | std::vector<BacktraceEntry> out; |
| 432 | return {}; | 432 | auto& memory = system.Memory(); |
| 433 | |||
| 434 | out.push_back({"", 0, pc, 0, ""}); | ||
| 435 | |||
| 436 | // fp (= r11) points to the last frame record. | ||
| 437 | // Frame records are two words long: | ||
| 438 | // fp+0 : pointer to previous frame record | ||
| 439 | // fp+4 : value of lr for frame | ||
| 440 | while (true) { | ||
| 441 | out.push_back({"", 0, lr, 0, ""}); | ||
| 442 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { | ||
| 443 | break; | ||
| 444 | } | ||
| 445 | lr = memory.Read32(fp + 4); | ||
| 446 | fp = memory.Read32(fp); | ||
| 447 | } | ||
| 448 | |||
| 449 | SymbolicateBacktrace(system, out); | ||
| 450 | |||
| 451 | return out; | ||
| 433 | } | 452 | } |
| 434 | 453 | ||
| 435 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext( | 454 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext( |
| 436 | System& system, const ThreadContext32& ctx) { | 455 | System& system, const ThreadContext32& ctx) { |
| 437 | return GetBacktrace(system, ctx.cpu_registers[13], ctx.cpu_registers[14]); | 456 | const auto& reg = ctx.cpu_registers; |
| 457 | return GetBacktrace(system, reg[11], reg[14], reg[15]); | ||
| 438 | } | 458 | } |
| 439 | 459 | ||
| 440 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const { | 460 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const { |
| 441 | return GetBacktrace(system, GetReg(13), GetReg(14)); | 461 | return GetBacktrace(system, GetReg(11), GetReg(14), GetReg(15)); |
| 442 | } | 462 | } |
| 443 | 463 | ||
| 444 | } // namespace Core | 464 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index fcbe24f0c..346e9abf8 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -78,7 +78,7 @@ protected: | |||
| 78 | private: | 78 | private: |
| 79 | std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; | 79 | std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; |
| 80 | 80 | ||
| 81 | static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 sp, u64 lr); | 81 | static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc); |
| 82 | 82 | ||
| 83 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; | 83 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; |
| 84 | using JitCacheType = | 84 | using JitCacheType = |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 92266aa9e..c437f24b8 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -494,22 +494,22 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, | |||
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, | 496 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, |
| 497 | u64 fp, u64 lr) { | 497 | u64 fp, u64 lr, u64 pc) { |
| 498 | std::vector<BacktraceEntry> out; | 498 | std::vector<BacktraceEntry> out; |
| 499 | auto& memory = system.Memory(); | 499 | auto& memory = system.Memory(); |
| 500 | 500 | ||
| 501 | // fp (= r29) points to the last frame record. | 501 | out.push_back({"", 0, pc, 0, ""}); |
| 502 | // Note that this is the frame record for the *previous* frame, not the current one. | 502 | |
| 503 | // Note we need to subtract 4 from our last read to get the proper address | 503 | // fp (= x29) points to the previous frame record. |
| 504 | // Frame records are two words long: | 504 | // Frame records are two words long: |
| 505 | // fp+0 : pointer to previous frame record | 505 | // fp+0 : pointer to previous frame record |
| 506 | // fp+8 : value of lr for frame | 506 | // fp+8 : value of lr for frame |
| 507 | while (true) { | 507 | while (true) { |
| 508 | out.push_back({"", 0, lr, 0, ""}); | 508 | out.push_back({"", 0, lr, 0, ""}); |
| 509 | if (!fp) { | 509 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { |
| 510 | break; | 510 | break; |
| 511 | } | 511 | } |
| 512 | lr = memory.Read64(fp + 8) - 4; | 512 | lr = memory.Read64(fp + 8); |
| 513 | fp = memory.Read64(fp); | 513 | fp = memory.Read64(fp); |
| 514 | } | 514 | } |
| 515 | 515 | ||
| @@ -520,11 +520,12 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::S | |||
| 520 | 520 | ||
| 521 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext( | 521 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext( |
| 522 | System& system, const ThreadContext64& ctx) { | 522 | System& system, const ThreadContext64& ctx) { |
| 523 | return GetBacktrace(system, ctx.cpu_registers[29], ctx.cpu_registers[30]); | 523 | const auto& reg = ctx.cpu_registers; |
| 524 | return GetBacktrace(system, reg[29], reg[30], ctx.pc); | ||
| 524 | } | 525 | } |
| 525 | 526 | ||
| 526 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const { | 527 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const { |
| 527 | return GetBacktrace(system, GetReg(29), GetReg(30)); | 528 | return GetBacktrace(system, GetReg(29), GetReg(30), GetPC()); |
| 528 | } | 529 | } |
| 529 | 530 | ||
| 530 | } // namespace Core | 531 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 71dbaac5e..c77a83ad7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -73,7 +73,7 @@ private: | |||
| 73 | std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, | 73 | std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, |
| 74 | std::size_t address_space_bits) const; | 74 | std::size_t address_space_bits) const; |
| 75 | 75 | ||
| 76 | static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr); | 76 | static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc); |
| 77 | 77 | ||
| 78 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; | 78 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; |
| 79 | using JitCacheType = | 79 | using JitCacheType = |