diff options
| author | 2022-06-25 12:54:24 -0400 | |
|---|---|---|
| committer | 2022-06-25 12:54:24 -0400 | |
| commit | 8f8c0b69dc4d56a0bc29bf8a0e59921334a808a8 (patch) | |
| tree | 9e2be93615a1af7d43c7080e4073ff3032393d34 | |
| parent | Merge pull request #8491 from Morph1984/extra-assert (diff) | |
| download | yuzu-8f8c0b69dc4d56a0bc29bf8a0e59921334a808a8.tar.gz yuzu-8f8c0b69dc4d56a0bc29bf8a0e59921334a808a8.tar.xz yuzu-8f8c0b69dc4d56a0bc29bf8a0e59921334a808a8.zip | |
core/arm: better support for backtrace generation
Diffstat (limited to '')
| -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 6425e131f..6c9c9d96d 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 8c90c8be0..dc01d9d1c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -409,18 +409,38 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, | |||
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, | 411 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, |
| 412 | u64 sp, u64 lr) { | 412 | u64 fp, u64 lr, u64 pc) { |
| 413 | // No way to get accurate stack traces in A32 yet | 413 | std::vector<BacktraceEntry> out; |
| 414 | return {}; | 414 | auto& memory = system.Memory(); |
| 415 | |||
| 416 | out.push_back({"", 0, pc, 0, ""}); | ||
| 417 | |||
| 418 | // fp (= r11) points to the last frame record. | ||
| 419 | // Frame records are two words long: | ||
| 420 | // fp+0 : pointer to previous frame record | ||
| 421 | // fp+4 : value of lr for frame | ||
| 422 | while (true) { | ||
| 423 | out.push_back({"", 0, lr, 0, ""}); | ||
| 424 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { | ||
| 425 | break; | ||
| 426 | } | ||
| 427 | lr = memory.Read32(fp + 4); | ||
| 428 | fp = memory.Read32(fp); | ||
| 429 | } | ||
| 430 | |||
| 431 | SymbolicateBacktrace(system, out); | ||
| 432 | |||
| 433 | return out; | ||
| 415 | } | 434 | } |
| 416 | 435 | ||
| 417 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext( | 436 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext( |
| 418 | System& system, const ThreadContext32& ctx) { | 437 | System& system, const ThreadContext32& ctx) { |
| 419 | return GetBacktrace(system, ctx.cpu_registers[13], ctx.cpu_registers[14]); | 438 | const auto& reg = ctx.cpu_registers; |
| 439 | return GetBacktrace(system, reg[11], reg[14], reg[15]); | ||
| 420 | } | 440 | } |
| 421 | 441 | ||
| 422 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const { | 442 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const { |
| 423 | return GetBacktrace(system, GetReg(13), GetReg(14)); | 443 | return GetBacktrace(system, GetReg(11), GetReg(14), GetReg(15)); |
| 424 | } | 444 | } |
| 425 | 445 | ||
| 426 | } // namespace Core | 446 | } // 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 4370ca294..8a20774e4 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -480,22 +480,22 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, | |||
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, | 482 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, |
| 483 | u64 fp, u64 lr) { | 483 | u64 fp, u64 lr, u64 pc) { |
| 484 | std::vector<BacktraceEntry> out; | 484 | std::vector<BacktraceEntry> out; |
| 485 | auto& memory = system.Memory(); | 485 | auto& memory = system.Memory(); |
| 486 | 486 | ||
| 487 | // fp (= r29) points to the last frame record. | 487 | out.push_back({"", 0, pc, 0, ""}); |
| 488 | // Note that this is the frame record for the *previous* frame, not the current one. | 488 | |
| 489 | // Note we need to subtract 4 from our last read to get the proper address | 489 | // fp (= x29) points to the previous frame record. |
| 490 | // Frame records are two words long: | 490 | // Frame records are two words long: |
| 491 | // fp+0 : pointer to previous frame record | 491 | // fp+0 : pointer to previous frame record |
| 492 | // fp+8 : value of lr for frame | 492 | // fp+8 : value of lr for frame |
| 493 | while (true) { | 493 | while (true) { |
| 494 | out.push_back({"", 0, lr, 0, ""}); | 494 | out.push_back({"", 0, lr, 0, ""}); |
| 495 | if (!fp) { | 495 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { |
| 496 | break; | 496 | break; |
| 497 | } | 497 | } |
| 498 | lr = memory.Read64(fp + 8) - 4; | 498 | lr = memory.Read64(fp + 8); |
| 499 | fp = memory.Read64(fp); | 499 | fp = memory.Read64(fp); |
| 500 | } | 500 | } |
| 501 | 501 | ||
| @@ -506,11 +506,12 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::S | |||
| 506 | 506 | ||
| 507 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext( | 507 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext( |
| 508 | System& system, const ThreadContext64& ctx) { | 508 | System& system, const ThreadContext64& ctx) { |
| 509 | return GetBacktrace(system, ctx.cpu_registers[29], ctx.cpu_registers[30]); | 509 | const auto& reg = ctx.cpu_registers; |
| 510 | return GetBacktrace(system, reg[29], reg[30], ctx.pc); | ||
| 510 | } | 511 | } |
| 511 | 512 | ||
| 512 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const { | 513 | std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const { |
| 513 | return GetBacktrace(system, GetReg(29), GetReg(30)); | 514 | return GetBacktrace(system, GetReg(29), GetReg(30), GetPC()); |
| 514 | } | 515 | } |
| 515 | 516 | ||
| 516 | } // namespace Core | 517 | } // 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 = |